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 Schedulable

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 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? } ):



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

def contact_name
  @contact_name
end

#noteObject (readonly)



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

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

#party_nameObject

Returns the value of attribute party_name.



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

def party_name
  @party_name
end

#roleObject (readonly)

validate :name_present

Validations:



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

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

Class Method Details

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



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
145
# File 'app/models/support_case_participant.rb', line 91

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



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

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



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

def self.roles
  ROLES.keys
end

.with_partyActiveRecord::Relation<SupportCaseParticipant>

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

Returns:

See Also:



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

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:



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

def communication_resource
  support_case
end

#contact_pointsActiveRecord::Relation<ContactPoint>

Returns:

See Also:



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

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



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

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



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

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

#emailContactPoint



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

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

#email_idObject



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

def email_id
  contact_points.emails.first&.id
end

#faxContactPoint



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

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

#name_presentObject



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

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



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

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:



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

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

#phoneContactPoint



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

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

#save_partyObject



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

def save_party
  party&.save
  true
end

#send_notification_emailObject



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

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



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
196
# File 'app/models/support_case_participant.rb', line 155

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:



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

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

#to_sObject



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

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