Class: SupportCaseParticipant

Inherits:
ApplicationRecord show all
Includes:
Models::Auditable, Models::LiquidMethods
Defined in:
app/models/support_case_participant.rb

Overview

== Schema Information

Table name: support_case_participants
Database name: primary

id :integer not null, primary key
note :string(255)
notify :boolean
preferred_language :string
role :string(255)
created_at :datetime not null
updated_at :datetime not null
email_id :integer
fax_id :integer
party_id :integer
phone_id :integer
support_case_id :integer

Indexes

by_pid_scid (party_id,support_case_id)
idx_support_case_participants_unique_party (support_case_id,party_id) UNIQUE
support_case_participants_email_id_idx (email_id)
support_case_participants_fax_id_idx (fax_id)
support_case_participants_phone_id_idx (phone_id)

Foreign Keys

fk_rails_... (email_id => contact_points.id)
fk_rails_... (fax_id => contact_points.id)
fk_rails_... (party_id => parties.id) ON DELETE => cascade
fk_rails_... (phone_id => contact_points.id)
fk_rails_... (support_case_id => support_cases.id) ON DELETE => cascade

Constant Summary collapse

ROLES =

Roles.

{
  'unknown' => ProfileConstants::HOMEOWNER,
  'electrician' => ProfileConstants::ELECTRICIAN,
  'installer' => ProfileConstants::INSTALLER,
  'iso' => ProfileConstants::UNKNOWN_TRADE,
  'store' => ProfileConstants::DEALER,
  'homeowner' => ProfileConstants::HOMEOWNER,
  'other trade' => ProfileConstants::UNKNOWN_TRADE
}.freeze

Constants included from Models::Auditable

Models::Auditable::ALWAYS_IGNORED

Constants included from Models::Schedulable

Models::Schedulable::SIMPLE_FORM_OPTIONS

Instance Attribute Summary collapse

Belongs to collapse

Methods included from Models::Auditable

#creator, #updater

Has many collapse

Class Method Summary collapse

Instance Method Summary collapse

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

config

Methods included from Models::AfterCommittable

#after_commit

Methods included from Models::EventPublishable

#publish_event

Instance Attribute Details

#contact_nameObject

Returns the value of attribute contact_name.

Validations (if => -> { party&.new_record? } ):



51
52
53
# File 'app/models/support_case_participant.rb', line 51

def contact_name
  @contact_name
end

#noteObject (readonly)



67
# File 'app/models/support_case_participant.rb', line 67

validates :note, length: { maximum: 255 }, allow_blank: true

#party_nameObject

Returns the value of attribute party_name.



51
52
53
# File 'app/models/support_case_participant.rb', line 51

def party_name
  @party_name
end

#roleObject (readonly)

validate :name_present

Validations:



66
# File 'app/models/support_case_participant.rb', line 66

validates :party, :support_case, :role, presence: true

Class Method Details

.find_participants(support_case, params = {}) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'app/models/support_case_participant.rb', line 90

def self.find_participants(support_case, params = {})
  results_array = []
  results = []
  matched_detail = nil
  raw_search_term = nil
  per_page = params[:per_page].to_i.nonzero? || 10
  page = params[:page].to_i.nonzero? || 1
  if (search_term = params[:q].presence&.strip)
    raw_search_term = search_term
    if (cn_term = search_term.scan(Customer::REFERENCE_NUMBER_PATTERN).join.upcase.presence)
      results += Customer.where(id: cn_term).to_a
      matched_detail = "CN#{cn_term}"
    elsif !search_term.match?(/[a-zA-Z]/) && (phone = PhoneNumber.parse(search_term))
      results = Party.customer_or_contact.joins(:contact_points).merge(ContactPoint.dialable.where(detail: phone.to_s)).limit(per_page).offset((page - 1) * per_page).to_a
      matched_detail = phone.format(:crm)
    elsif search_term.match?(/\A[^@\s]+@[^@\s]+\z/)
      email = search_term.downcase
      results = Party.customer_or_contact.joins(:contact_points).merge(ContactPoint.emails.contains(email)).limit(per_page).offset((page - 1) * per_page).to_a
      matched_detail = email
    else # wild card lookup
      results += Party.customer_or_contact.lookup(search_term).limit(per_page).offset((page - 1) * per_page).to_a
    end
    # If we don't have a search term but we have a party_id we can load up suggested participants
  end
  if results.blank?
    matched_detail = nil
    raw_search_term = nil
    if support_case
      results = support_case.suggested_participants
    elsif (party_id = params[:participant_id]).present?
      # Basically all contacts of the customer of that party
      party = Party.customer_or_contact.find(party_id)
      if party.customer
        results = party.customer.contacts.active.order(:full_name)
        results = results.where.not(id: params[:existing_participant_ids]) if params[:existing_participant_ids].present?
        results = results.to_a
      end
    end
  end

  if results.present?
    results_array += results.uniq.map do |party|
      entry = { text: party.to_s, id: party.id }
      if matched_detail
        entry[:text] = "#{party}#{matched_detail}"
        entry[:match] = raw_search_term
      end
      entry
    end
  end
  results_array = results_array.sort_by { |r| r[:text] }

  total_entries = results.size
  { results: results_array, total: total_entries }
end

.migrate_cpObject

TEMP METHOD



251
252
253
254
255
256
257
258
259
260
# File 'app/models/support_case_participant.rb', line 251

def self.migrate_cp
  support_case_participants = SupportCaseParticipant.select('parties.id, party_id, phone_id, email_id, fax_id').eager_load(:party)
  support_case_participants.find_each do |scp|
    sc_cp_ids = [scp.phone_id, scp.email_id, scp.fax_id].compact.uniq
    if sc_cp_ids.present? && scp.party_id
      puts "Updating contact points #{sc_cp_ids.join(', ')} with party_id: #{scp.party_id}"
      ContactPoint.where(id: sc_cp_ids).where(party_id: nil).update_all(party_id: scp.party_id)
    end
  end
end

.rolesObject



220
221
222
# File 'app/models/support_case_participant.rb', line 220

def self.roles
  ROLES.keys
end

.with_partyActiveRecord::Relation<SupportCaseParticipant>

A relation of SupportCaseParticipants that are with party. Active Record Scope

Returns:

See Also:



61
# File 'app/models/support_case_participant.rb', line 61

scope :with_party, -> { joins(:party).eager_load(:party) }

Instance Method Details

#communication_resourceSupportCase?

Alias for #support_case, exposed as communication_resource for the
generic communication-resource interface used across the CRM.

Returns:



86
87
88
# File 'app/models/support_case_participant.rb', line 86

def communication_resource
  support_case
end

#contact_pointsActiveRecord::Relation<ContactPoint>

Returns:

See Also:



59
# File 'app/models/support_case_participant.rb', line 59

has_many :contact_points, through: :party

#default_catalog_idObject

Best guess at what catalog this support case belongs to so we can determine the catalog id to use by default
on new participants



204
205
206
207
208
209
# File 'app/models/support_case_participant.rb', line 204

def default_catalog_id
  if (pp = support_case&.primary_party && pp.respond_to?(:customer))
    cat_id = pp.customer&.catalog_id || CatalogConstants::US_CATALOG_ID
  end
  cat_id || CatalogConstants::US_CATALOG_ID
end

#default_source_idObject



211
212
213
214
215
216
217
218
# File 'app/models/support_case_participant.rb', line 211

def default_source_id
  case support_case&.case_type
  when 'Tech'
    1053
  when 'Ecommerce'
    853
  end
end

#emailContactPoint



55
# File 'app/models/support_case_participant.rb', line 55

belongs_to :email, class_name: 'ContactPoint', inverse_of: :email_support_case_participants, optional: true

#email_idObject



224
225
226
# File 'app/models/support_case_participant.rb', line 224

def email_id
  contact_points.emails.first&.id
end

#faxContactPoint



57
# File 'app/models/support_case_participant.rb', line 57

belongs_to :fax, class_name: 'ContactPoint', inverse_of: :fax_support_case_participants, optional: true

#name_presentObject



146
147
148
149
150
151
152
# File 'app/models/support_case_participant.rb', line 146

def name_present
  return if persisted? # Only check for new participants
  return if party_name.presence || contact_name.presence

  errors.add(:base, "Participant name can't be blank")
  nil
end

#new_ticket_system_codeObject



232
233
234
235
236
237
238
239
240
241
# File 'app/models/support_case_participant.rb', line 232

def new_ticket_system_code
  case support_case.case_type
  when 'Accounting'
    'ACCT_TCKT_NEW'
  when 'Ecommerce'
    'ECOM_TCKT_NEW'
  else
    'TICKET_NEW'
  end
end

#partyParty

Returns:

See Also:

Validations:



53
# File 'app/models/support_case_participant.rb', line 53

belongs_to :party, inverse_of: :support_case_participants, optional: true

#phoneContactPoint



56
# File 'app/models/support_case_participant.rb', line 56

belongs_to :phone, class_name: 'ContactPoint', inverse_of: :phone_support_case_participants, optional: true

#save_partyObject



197
198
199
200
# File 'app/models/support_case_participant.rb', line 197

def save_party
  party&.save
  true
end

#send_notification_emailObject



228
229
230
# File 'app/models/support_case_participant.rb', line 228

def send_notification_email
  CommunicationBuilder.new(resource: self, template_system_code: new_ticket_system_code, recipient_party: party, recipient_contact_point_id: email_id).create
end

#set_partyObject



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'app/models/support_case_participant.rb', line 154

def set_party
  # Store contact points from form
  contact_points = party.contact_points.to_a if party&.new_record?
  contact_points ||= []

  customer_name = party_name.presence || contact_name.presence
  return if customer_name.blank? || role.blank? || party_id.present?

  c = Customer.new(catalog_id: default_catalog_id,
                   profile_id: ROLES[role],
                   source_id: default_source_id)
  if c.is_homeowner?
    pnp = PersonNameParser.new(customer_name)
    pnp.to_party(c)
  else
    c.full_name = customer_name
  end
  con = nil
  if c.valid?
    if contact_name.present? && contact_name != customer_name
      pnp = PersonNameParser.new(contact_name)
      con = Contact.new(customer: c)
      pnp.to_party(con)
      if con.valid?
        # Contact is the party
        self.party = con
      else
        errors.add(:contact_name, con.errors.full_messages)
      end
    else
      # Customer is the party
      self.party = c
    end
  else
    errors.add(:party_name, c.errors.full_messages)
  end

  # Carry over previously set contact points over to this new party
  return if contact_points.blank?

  contact_points.each { |cp| party.contact_points << cp unless party.contact_points.find { |ecp| ecp == cp } }
end

#support_caseSupportCase

Validations:



54
# File 'app/models/support_case_participant.rb', line 54

belongs_to :support_case, inverse_of: :support_case_participants, optional: true

#to_sObject



243
244
245
246
247
248
# File 'app/models/support_case_participant.rb', line 243

def to_s
  n = []
  n << party&.customer&.full_name
  n << party&.full_name
  n.compact.join(' - ')
end