Class: OpportunityParticipant

Inherits:
ApplicationRecord show all
Defined in:
app/models/opportunity_participant.rb

Overview

== Schema Information

Table name: opportunity_participants
Database name: primary

id :integer not null, primary key
role :string
created_at :datetime
updated_at :datetime
contact_point_id :integer
creator_id :integer
opportunity_id :integer not null
party_id :integer not null
updater_id :integer

Indexes

index_opportunity_participants_on_opportunity_id_and_party_id (opportunity_id,party_id) UNIQUE
opportunity_participants_contact_point_id_idx (contact_point_id)
opportunity_participants_party_id_idx (party_id)

Foreign Keys

fk_rails_... (contact_point_id => contact_points.id)
fk_rails_... (opportunity_id => opportunities.id)
fk_rails_... (party_id => parties.id)

Constant Summary collapse

MAX_INTEGER_ID =

Max value for 4-byte signed integer (PostgreSQL integer type)

2_147_483_647

Belongs to collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from ApplicationRecord

ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation

Methods included from Models::EventPublishable

#publish_event

Class Method Details

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



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
146
147
148
149
150
151
152
153
154
155
# File 'app/models/opportunity_participant.rb', line 100

def self.find_participants(opportunity, params = {})
  results_array = []
  if search_term = params[:q].presence
    in_customer_results = opportunity.customer.contacts.active.order(:full_name)
    results = []
    # Only query by ID if the search term is a valid integer within range
    search_term_as_id = search_term.to_i if search_term.to_s.match?(/\A\d+\z/) && search_term.to_i <= MAX_INTEGER_ID
    results += in_customer_results.where(id: search_term_as_id) if search_term_as_id
    # Build name match query, only include ID match if within range
    name_match = Contact[:full_name].matches("%#{search_term}%")
    name_match = name_match.or(Contact[:id].eq(search_term_as_id)) if search_term_as_id
    results += in_customer_results.where(name_match)
    if results.present?
      results_array = [{ text: "#{opportunity.customer.full_name}'s Contacts Matches:" }]
      results_array += results.uniq.map { |party| { id: party.id, text: "#{party.full_name} [#{party.id}]" } }
    end
    results_array += ["NewContactOfCustomer|#{opportunity.customer_id}|#{search_term}",
                      "NewContact|#{opportunity.id}|#{search_term}",
                      "NewCustomer|#{opportunity.id}|#{search_term}"].map { |party_combo| { text: party_combo_description(party_combo, opportunity), id: party_combo } }

    # Do wildcard lookup outside of this opportunity's customer
    # for some reason this exclusion makes the look up fail to find anyone
    # where.not('parties.customer_id = :customer_id OR parties.id = :customer_id', customer_id: opportunity.customer_id)
    per_page = (params[:per_page] || 10).to_i
    page = (params[:page] || 1).to_i
    global_results = Party.where(type: %w[Customer Contact]).lookup(search_term).limit(per_page).offset((page - 1) * per_page).to_a
    if cn_term = search_term.scan(Customer::REFERENCE_NUMBER_PATTERN).join.upcase.presence
      global_results += Customer.where(id: cn_term).to_a
    elsif search_term_as_id # Only query by ID if within valid integer range
      global_results += Customer.where(id: search_term_as_id).to_a
    end
    if global_results.present?
      global_results.compact.uniq.each do |party|
        results_array << format_party_for_results(party)
        next unless party.respond_to? :contacts

        if (contacts = party.contacts.active.order(:full_name)).present?
          results_array += contacts.map { |contact| format_party_for_results(contact) }
        end
      end
    end
  else
    party_ids = []
    # Input is preselected with an id, load it up
    if params[:party_id].present?
      party_ids << params[:party_id].to_i # Form loaded with a part selected
    end
    # Add the opportunity's parties
    party_ids += opportunity.customer.contacts.active.order(:full_name).pluck(:id)
    results = Party.where(id: party_ids.compact.uniq)
    results_array += results.to_a.uniq.map { |party| format_party_for_results(party) }
  end

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

.format_party_for_results(party) ⇒ Object



157
158
159
160
161
162
163
164
165
166
167
168
# File 'app/models/opportunity_participant.rb', line 157

def self.format_party_for_results(party)
  display_text = if party.is_a?(Contact)
                   if party.customer
                     "#{party.customer.try(:full_name)} (#{party.customer.reference_number}) • #{party.full_name}"
                   else
                     "#{party.full_name}"
                   end
                 else
                   "#{party.full_name} (#{party.reference_number})"
                 end
  { id: party.id, text: display_text }
end

.party_combo_description(party_combo, opportunity = nil) ⇒ Object



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'app/models/opportunity_participant.rb', line 72

def self.party_combo_description(party_combo, opportunity = nil)
  parts = party_combo.to_s.split('|')
  action, record_id, name = *parts
  opportunity ||= Opportunity.find(record_id)
  case action
  when 'NewContactOfCustomer'
    "Create #{name} as contact of #{opportunity.customer.full_name}"
  when 'NewContact'
    "Create #{name} as contact only for this opportunity"
  when 'NewCustomer'
    "Create #{name} as new customer"
  else
    nil
  end
end

Instance Method Details

#contactObject



45
46
47
# File 'app/models/opportunity_participant.rb', line 45

def contact
  party.is_a?(Contact) && party
end

#contact_pointContactPoint



36
# File 'app/models/opportunity_participant.rb', line 36

belongs_to :contact_point, inverse_of: :opportunity_participants, optional: true

#contact_point_detailObject



53
54
55
# File 'app/models/opportunity_participant.rb', line 53

def contact_point_detail
  contact_point.try(:detail) || party_primary_contact_point_detail || @contact_point_detail
end

#contact_point_detail=(val) ⇒ Object



57
58
59
60
# File 'app/models/opportunity_participant.rb', line 57

def contact_point_detail=(val)
  contact_point_id_will_change!
  @contact_point_detail = val
end

#customerObject



49
50
51
# File 'app/models/opportunity_participant.rb', line 49

def customer
  (contact && contact.customer) || (party.is_a?(Customer) && party)
end

#opportunityOpportunity



34
# File 'app/models/opportunity_participant.rb', line 34

belongs_to :opportunity, inverse_of: :opportunity_participants, optional: true

#partyParty

Returns:

See Also:



35
# File 'app/models/opportunity_participant.rb', line 35

belongs_to :party, inverse_of: :opportunity_participants, optional: true

#party_comboObject



93
94
95
# File 'app/models/opportunity_participant.rb', line 93

def party_combo
  party_id || @party_combo
end

#party_combo=(val) ⇒ Object



88
89
90
91
# File 'app/models/opportunity_participant.rb', line 88

def party_combo=(val)
  party_id_will_change!
  @party_combo = val
end

#party_combo_for_selectObject

Gets called to populate our initial select options



63
64
65
66
67
68
69
70
# File 'app/models/opportunity_participant.rb', line 63

def party_combo_for_select
  if party_id
    output = self.class.format_party_for_results(party)
    [[output[:text], output[:id]]]
  elsif @party_combo
    [[self.class.party_combo_description(@party_combo, opportunity), @party_combo]]
  end
end

#party_primary_contact_point_detailObject



170
171
172
# File 'app/models/opportunity_participant.rb', line 170

def party_primary_contact_point_detail
  party && party.contact_points.sort_by(&:position).detect(&:contactable?).try(:detail)
end

#roles_for_selectObject



40
41
42
43
# File 'app/models/opportunity_participant.rb', line 40

def roles_for_select
  options = [role] + Profile.where.not(name: 'Buying Group').map(&:friendly_name).sort
  options.compact.uniq.sort
end