Class: Activity
Overview
== Schema Information
Table name: activities
Database name: primary
id :integer not null, primary key
completion_datetime :datetime
description :string(255)
lock_target_datetime :boolean default(FALSE)
notes :text
original_target_datetime :datetime
resource_type :string(255)
start_datetime :datetime
target_datetime :datetime
uploads_count :integer default(0)
created_at :datetime
updated_at :datetime
activity_result_type_id :integer
activity_type_id :integer
assigned_resource_id :integer
campaign_id :integer
closed_by_id :integer
communication_id :integer
creator_id :integer
customer_id :integer
opportunity_id :integer
original_assigned_resource_id :integer
parent_activity_id :integer
party_id :integer
resource_id :integer
updater_id :integer
visit_id :integer
Indexes
by_act_type_w (activity_type_id) WHERE (activity_result_type_id IS NULL)
by_type_and_assi_resrc_w (activity_type_id,assigned_resource_id) WHERE (activity_result_type_id IS NULL)
index_activities_on_activity_result_type_id (activity_result_type_id)
index_activities_on_activity_type_id (activity_type_id)
index_activities_on_assigned_resource_id (assigned_resource_id)
index_activities_on_campaign_id (campaign_id)
index_activities_on_closed_by_id (closed_by_id)
index_activities_on_communication_id (communication_id)
index_activities_on_creator_id (creator_id)
index_activities_on_customer_id (customer_id)
index_activities_on_opportunity_id (opportunity_id)
index_activities_on_party_id (party_id)
index_activities_on_resource_type_and_resource_id (resource_type,resource_id) WHERE ((resource_type IS NOT NULL) AND (resource_id IS NOT NULL))
index_activities_on_target_datetime (target_datetime) USING brin
index_activities_on_updater_id (updater_id)
index_activities_on_visit_id (visit_id)
index_activities_resource_id (resource_id)
Foreign Keys
activities_activity_result_type_id_fkey (activity_result_type_id => activity_result_types.id)
activities_activity_type_id_fkey (activity_type_id => activity_types.id)
activities_communication_id_fk (communication_id => communications.id) ON DELETE => nullify
activities_creator_id_fk (creator_id => parties.id) ON DELETE => nullify
activities_party_id_fk (party_id => parties.id) ON DELETE => cascade
activities_updater_id_fk (updater_id => parties.id) ON DELETE => nullify
fk_rails_... (customer_id => parties.id)
fk_rails_... (opportunity_id => opportunities.id) ON DELETE => nullify ON UPDATE => cascade
fk_rails_... (visit_id => visits.id)
Defined Under Namespace
Classes: AssignmentNotificationHandler, AutoChainCloser, ChainRunner, ChainRunnerHandler, CompactNotes, EmailNotificationHandler, ExpiredActivityCloser, OpenActivitiesStamper, Prioritizer, ResourceList, SalesActivityHandler, SynchronousEffectsHandler, TypeRulesCreatedHandler, TypeRulesUpdatedHandler, VoicemailReadHandler
Constant Summary
collapse
- NOTE_RESULT_ID =
2
- NATURAL_ORDER =
'activities.activity_result_type_id IS NULL DESC, COALESCE(activities.completion_datetime,activities.target_datetime) DESC'
- RESOURCE_TYPES =
%w[Delivery Opportunity Order SupportCase Party SpiffEnrollment Receipt CreditMemo SupportCaseParticipant StatementOfAccount Rma Invoice RoomConfiguration ExportedCatalogItemPacket LocatorRecord CreditApplication CampaignDelivery
PurchaseOrder Payment Quote SchedulerBooking CallRecord].freeze
- FINAL_SERVICES =
[ActivityTypeConstants::ONSITESERVICE, ActivityTypeConstants::SSI_INSTALL, ActivityTypeConstants::SGS_ONSITESUPPORT, ActivityTypeConstants::SGS_REMOTESUPPORT, ActivityTypeConstants::SSFIX_ONSITE_SERVICE]
- INITIAL_SERVICES =
[ActivityTypeConstants::SERVICECONFIRM, ActivityTypeConstants::SSI_PREPLAN_MEET, ActivityTypeConstants::SGS_ONSITE_PREPLAN_MEET, ActivityTypeConstants::SGS_REMOTE_PREPLAN_MEET, ActivityTypeConstants::SSFIX_SERVICE_CONFIRM]
- MIN_EMBEDDABLE_NOTES_LENGTH =
50
Models::Embeddable::DEFAULT_MODEL, Models::Embeddable::MAX_CONTENT_LENGTH
Models::Auditable::ALWAYS_IGNORED
Instance Attribute Summary collapse
#creator, #updater
#content_embeddings
Has and belongs to many
collapse
Delegated Instance Attributes
collapse
Class Method Summary
collapse
Instance Method Summary
collapse
#embeddable_locales, #embedding_content_hash, embedding_partition_class, #embedding_stale?, #embedding_type_name, #embedding_vector, #find_content_embedding, #find_similar, #generate_all_embeddings!, #generate_chunked_embeddings!, #generate_embedding!, #has_embedding?, #locale_for_embedding, #needs_chunking?, regenerate_all_embeddings, semantic_search
#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record
ransackable_associations, ransackable_attributes, ransortable_attributes, #to_relation
#publish_event
Instance Attribute Details
#assignment_resource_ids ⇒ Object
Returns the value of attribute assignment_resource_ids.
243
244
245
|
# File 'app/models/activity.rb', line 243
def assignment_resource_ids
@assignment_resource_ids
end
|
#chained_activity_result ⇒ Object
Returns the value of attribute chained_activity_result.
243
244
245
|
# File 'app/models/activity.rb', line 243
def chained_activity_result
@chained_activity_result
end
|
#fallback_employee_id ⇒ Object
Returns the value of attribute fallback_employee_id.
243
244
245
|
# File 'app/models/activity.rb', line 243
def fallback_employee_id
@fallback_employee_id
end
|
#halt_chain ⇒ Object
Returns the value of attribute halt_chain.
243
244
245
|
# File 'app/models/activity.rb', line 243
def halt_chain
@halt_chain
end
|
#linked_party_ids ⇒ Object
Returns the value of attribute linked_party_ids.
243
244
245
|
# File 'app/models/activity.rb', line 243
def linked_party_ids
@linked_party_ids
end
|
#mileage ⇒ Object
Returns the value of attribute mileage.
243
244
245
|
# File 'app/models/activity.rb', line 243
def mileage
@mileage
end
|
#new_target_date ⇒ Object
Returns the value of attribute new_target_date.
243
244
245
|
# File 'app/models/activity.rb', line 243
def new_target_date
@new_target_date
end
|
#new_target_time ⇒ Object
Returns the value of attribute new_target_time.
243
244
245
|
# File 'app/models/activity.rb', line 243
def new_target_time
@new_target_time
end
|
#service_date ⇒ Object
Returns the value of attribute service_date.
243
244
245
|
# File 'app/models/activity.rb', line 243
def service_date
@service_date
end
|
#service_duration ⇒ Object
Returns the value of attribute service_duration.
243
244
245
|
# File 'app/models/activity.rb', line 243
def service_duration
@service_duration
end
|
#service_time ⇒ Object
Returns the value of attribute service_time.
243
244
245
|
# File 'app/models/activity.rb', line 243
def service_time
@service_time
end
|
#skip_callbacks ⇒ Object
Returns the value of attribute skip_callbacks.
243
244
245
|
# File 'app/models/activity.rb', line 243
def skip_callbacks
@skip_callbacks
end
|
#skip_check_for_open_sales_activity ⇒ Object
Returns the value of attribute skip_check_for_open_sales_activity.
243
244
245
|
# File 'app/models/activity.rb', line 243
def skip_check_for_open_sales_activity
@skip_check_for_open_sales_activity
end
|
#skip_check_for_valid_party ⇒ Object
Returns the value of attribute skip_check_for_valid_party.
243
244
245
|
# File 'app/models/activity.rb', line 243
def skip_check_for_valid_party
@skip_check_for_valid_party
end
|
#support_case_closed_reason ⇒ Object
Returns the value of attribute support_case_closed_reason.
243
244
245
|
# File 'app/models/activity.rb', line 243
def support_case_closed_reason
@support_case_closed_reason
end
|
#support_case_event ⇒ Object
Returns the value of attribute support_case_event.
243
244
245
|
# File 'app/models/activity.rb', line 243
def support_case_event
@support_case_event
end
|
#travel_time ⇒ Object
Returns the value of attribute travel_time.
243
244
245
|
# File 'app/models/activity.rb', line 243
def travel_time
@travel_time
end
|
#updated_activities ⇒ Object
Returns the value of attribute updated_activities.
243
244
245
|
# File 'app/models/activity.rb', line 243
def updated_activities
@updated_activities
end
|
Class Method Details
.all_activity_filters ⇒ Object
495
496
497
|
# File 'app/models/activity.rb', line 495
def self.all_activity_filters
%w[Party Contact Opportunity]
end
|
.completed ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are completed. Active Record Scope
115
|
# File 'app/models/activity.rb', line 115
scope :completed, -> { joins(:activity_result_type).merge(ActivityResultType.completed) }
|
.completion_order ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are completion order. Active Record Scope
120
|
# File 'app/models/activity.rb', line 120
scope :completion_order, -> { order('activities.completion_datetime desc') }
|
.embeddable_content_types ⇒ Object
-- Embeddable interface ---------------------------------------------------
549
550
551
|
# File 'app/models/activity.rb', line 549
def self.embeddable_content_types
[:primary]
end
|
.final_service_completed ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are final service completed. Active Record Scope
169
|
# File 'app/models/activity.rb', line 169
scope :final_service_completed, -> { where(activity_type_id: FINAL_SERVICES, activity_result_type_id: ActivityResultTypeConstants::CMP) }
|
A relation of Activities that are for customer and contacts. Active Record Scope
147
|
# File 'app/models/activity.rb', line 147
scope :for_customer_and_contacts, ->(customer) { where(party_id: customer.self_and_contacts_party_ids_arr) }
|
.heatwave_assistant_id ⇒ Object
608
609
610
|
# File 'app/models/activity.rb', line 608
def self.heatwave_assistant_id
Employee.joins(:contact_points).merge(ContactPoint.emails).where(ContactPoint[:detail].eq('hwav@warmlyyours.com')).pick(:id)
end
|
.high_priority ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are high priority. Active Record Scope
118
|
# File 'app/models/activity.rb', line 118
scope :high_priority, -> { joins(:activity_type).where(activity_types: { priority: 1 }) }
|
.inbound_emails ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are inbound emails. Active Record Scope
167
|
# File 'app/models/activity.rb', line 167
scope :inbound_emails, -> { where(activity_type_id: ActivityTypeConstants::EMAILIN_TYPES) }
|
.initial_service_completed ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are initial service completed. Active Record Scope
168
|
# File 'app/models/activity.rb', line 168
scope :initial_service_completed, -> { where(activity_type_id: INITIAL_SERVICES, activity_result_type_id: ActivityResultTypeConstants::CMP) }
|
.iqoppfu ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are iqoppfu. Active Record Scope
113
|
# File 'app/models/activity.rb', line 113
scope :iqoppfu, -> { where(activity_type_id: ActivityTypeConstants::IQOPPFUS_IDS) }
|
.leads ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are leads. Active Record Scope
114
|
# File 'app/models/activity.rb', line 114
scope :leads, -> { where(activity_type_id: ActivityTypeConstants::LEAD_FORM) }
|
.mcp_searchable? ⇒ Boolean
553
554
555
|
# File 'app/models/activity.rb', line 553
def self.mcp_searchable?
false
end
|
.meeting ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are meeting. Active Record Scope
122
|
# File 'app/models/activity.rb', line 122
scope :meeting, -> { joins(:activity_type).merge(ActivityType.meeting) }
|
.natural_order ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are natural order. Active Record Scope
119
|
# File 'app/models/activity.rb', line 119
scope :natural_order, -> { order(Arel.sql(NATURAL_ORDER)) }
|
.non_cob_time(datetime) ⇒ Object
584
585
586
587
588
589
590
591
|
# File 'app/models/activity.rb', line 584
def self.non_cob_time(datetime)
return unless datetime
closing_time = WorkingHours.advance_to_closing_time(datetime)
return unless datetime != closing_time && (datetime.min != 0)
datetime.strftime('%I:%M %p')
end
|
.non_notes ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are non notes. Active Record Scope
111
|
# File 'app/models/activity.rb', line 111
scope :non_notes, -> { where.not(activity_type_id: nil) }
|
.not_tagged_with ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are not tagged with. Active Record Scope
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
|
# File 'app/models/activity.rb', line 149
scope :not_tagged_with, ->(*tags) {
clean_tags = [tags].flatten.map(&:presence).compact.uniq.map(&:downcase)
return all if clean_tags.empty?
tagged_activity_type_ids = ActivityType.joins(:tag_records)
.where('LOWER(tags.name) IN (?)', clean_tags)
.distinct
.pluck(:id)
if tagged_activity_type_ids.any?
where('activities.activity_type_id IS NULL OR activities.activity_type_id NOT IN (?)', tagged_activity_type_ids)
else
all
end
}
|
.notes_only ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are notes only. Active Record Scope
110
|
# File 'app/models/activity.rb', line 110
scope :notes_only, -> { where(activity_type_id: nil) }
|
.open_activities ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are open activities. Active Record Scope
116
|
# File 'app/models/activity.rb', line 116
scope :open_activities, -> { where(activity_result_type_id: nil).non_notes }
|
.overdue_activities ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are overdue activities. Active Record Scope
117
|
# File 'app/models/activity.rb', line 117
scope :overdue_activities, -> { open_activities.where(Activity[:target_datetime].lteq(Time.current)) }
|
.position_of_activity(activity_id, relation) ⇒ Object
283
284
285
|
# File 'app/models/activity.rb', line 283
def self.position_of_activity(activity_id, relation)
relation.order(relation.values[:order] || :id).pluck(:id).index(activity_id).try(:+, 1)
end
|
.preloaded ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are preloaded. Active Record Scope
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
# File 'app/models/activity.rb', line 124
scope :preloaded, -> {
includes(
:party,
:activity_result_type,
:campaign,
{ activity_type: :tag_records },
{ assigned_resource: :profile_image },
{ closed_by: :profile_image },
{ communication: :uploads },
:resource_support_case,
:resource_opportunity,
:resource_order,
:resource_quote,
:resource_room_configuration,
:resource_scheduler_booking
)
}
|
.quofu ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are quofu. Active Record Scope
112
|
# File 'app/models/activity.rb', line 112
scope :quofu, -> { where(activity_type_id: ActivityTypeConstants::QUOFUS_IDS) }
|
.ransackable_scopes(_auth_object = nil) ⇒ Object
275
276
277
|
# File 'app/models/activity.rb', line 275
def self.ransackable_scopes(_auth_object = nil)
%i[tagged_with not_tagged_with]
end
|
.resource_types ⇒ Object
279
280
281
|
# File 'app/models/activity.rb', line 279
def self.resource_types
RESOURCE_TYPES
end
|
.sales_activities ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are sales activities. Active Record Scope
.tagged_with ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are tagged with. Active Record Scope
148
|
# File 'app/models/activity.rb', line 148
scope :tagged_with, ->(*tags) { joins(:activity_type).merge(ActivityType.tagged_with(tags)) }
|
.training ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are training. Active Record Scope
121
|
# File 'app/models/activity.rb', line 121
scope :training, -> { joins(:activity_type).merge(ActivityType.training) }
|
.visible_by_default ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are visible by default. Active Record Scope
166
|
# File 'app/models/activity.rb', line 166
scope :visible_by_default, -> { not_tagged_with(['Drip']) }
|
.with_activity_uploads_count ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are with activity uploads count. Active Record Scope
146
|
# File 'app/models/activity.rb', line 146
scope :with_activity_uploads_count, -> { select("activities.*, (select count(u.id) from uploads u where u.resource_type = 'Activity' and u.resource_id = activities.id) as uploads_count") }
|
.with_customer_as_c ⇒ ActiveRecord::Relation<Activity>
A relation of Activities that are with customer as c. Active Record Scope
142
143
144
145
|
# File 'app/models/activity.rb', line 142
scope :with_customer_as_c, -> {
joins('inner join parties p on p.id = activities.party_id')
.joins("left join parties c on ((p.type = 'Contact' and p.customer_id = c.id) or (p.type = 'Customer' and p.id = c.id))")
}
|
Instance Method Details
89
|
# File 'app/models/activity.rb', line 89
belongs_to :activity_result_type, inverse_of: :activities, optional: true
|
75
|
# File 'app/models/activity.rb', line 75
belongs_to :activity_type, inverse_of: :activities, optional: true
|
#activity_type_for_select ⇒ Object
331
332
333
|
# File 'app/models/activity.rb', line 331
def activity_type_for_select
ActivityType.options_for_select(party:, include_activity_type_id: activity_type_id)
end
|
#age_in_days ⇒ Object
287
288
289
290
|
# File 'app/models/activity.rb', line 287
def age_in_days
end_date = closed? ? completion_datetime.to_date : Date.current
(end_date - effective_origin_date).to_i
end
|
#assigned_resource ⇒ Employee
79
|
# File 'app/models/activity.rb', line 79
belongs_to :assigned_resource, class_name: 'Employee', optional: true
|
#auto_assign(allocate_on = nil, current_user = nil, options = {}) ⇒ Object
437
438
439
440
441
442
443
|
# File 'app/models/activity.rb', line 437
def auto_assign(allocate_on = nil, current_user = nil, options = {})
self.target_datetime ||= created_at self.original_target_datetime ||= target_datetime
self.target_datetime = allocate_on if allocate_on && !lock_target_datetime self.original_assigned_resource ||= assigned_resource
self.assigned_resource = best_resource_employee(current_user, options)
end
|
#auto_assign_and_schedule(ideal_target_date = nil, options = {}) ⇒ Object
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
|
# File 'app/models/activity.rb', line 408
def auto_assign_and_schedule(ideal_target_date = nil, options = {})
logger = options[:logger] || Rails.logger
original_scheduled_date = ideal_target_date || target_datetime
allocate_on = original_scheduled_date
return false unless allocate_on
begin
logger.debug "Processing activity #{id} with a target date of #{allocate_on}."
yield(allocate_on) if allocate_on.present? && block_given?
auto_assign(allocate_on, options) success = false if assigned_resource.present? save success = true allocate_on = nil elsif allocate_on > (original_scheduled_date + 1.month) allocate_on = nil logger.error ' * Could not find a suitable resource for activity after 30 days'
else allocate_on += 1.day
end
logger.debug " ** assigned resource is #{assigned_resource.try(:full_name)} allocate on is now #{allocate_on}"
end while allocate_on
success
end
|
#auto_close_if_applicable(auto_save: true) ⇒ Object
Our activity chain might have special rules, such as an auto close result when the due date is reached, useful for triggering
drip email chains
447
448
449
450
451
452
453
454
455
456
|
# File 'app/models/activity.rb', line 447
def auto_close_if_applicable(auto_save: true)
return :not_applicable if is_note? || closed?
return :not_applicable unless art = activity_type.auto_close_result_chain
return :not_overdue unless overdue? && art.due_date?
self.activity_result_type = art.activity_result_type
save! if auto_save
:overdue_auto_close
end
|
#best_resource(current_user = nil, options = {}) ⇒ Object
current_user: a value to use as the currently logged in user
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
|
# File 'app/models/activity.rb', line 459
def best_resource(current_user = nil, options = {})
return nil if is_note?
current_user = nil unless current_user.is_a?(Employee)
current_user ||= self.original_assigned_resource
current_user ||= creator if creator.is_a?(Employee)
current_user ||= updater if updater.is_a?(Employee)
at = activity_type
if (resource.class == SupportCase) && customer.nil?
resource.assigned_to_id || at.activity_type_assignment_queues.first.try(:fallback_employee_id) || current_user
elsif customer
at.determine_assigned_resource_id(customer, current_user.try(:id), self.target_datetime, resource, options)
end
end
|
#best_resource_employee(current_user = nil, options = {}) ⇒ Object
475
476
477
478
479
480
|
# File 'app/models/activity.rb', line 475
def best_resource_employee(current_user = nil, options = {})
rep_id = best_resource(current_user, options)
return Employee.find(rep_id) if rep_id
nil
end
|
91
|
# File 'app/models/activity.rb', line 91
belongs_to :campaign, optional: true
|
#campaign_options_for_select ⇒ Object
356
357
358
359
360
361
362
363
|
# File 'app/models/activity.rb', line 356
def campaign_options_for_select
options = []
if customer = party.try(:customer) || resource.try(:customer)
options = Campaign.joins(subscriber_lists: :subscribers).where(subscribers: { customer_id: customer.id }).pluck(:name, :id)
options << [campaign.name, campaign.id] if campaign
end
options.compact.uniq
end
|
#cancel(options = {}) ⇒ Object
537
538
539
540
|
# File 'app/models/activity.rb', line 537
def cancel(options = {})
opts = { activity_result_type_id: ActivityResultTypeConstants::CANCEL, completion_datetime: Time.current }.merge(options)
update(opts)
end
|
#cancelled? ⇒ Object
Alias for Activity_result_type#cancelled?
183
|
# File 'app/models/activity.rb', line 183
delegate :complete?, :cancelled?, :result_code, to: :activity_result_type, allow_nil: true
|
#child_activities ⇒ ActiveRecord::Relation<Activity>
96
|
# File 'app/models/activity.rb', line 96
has_many :child_activities, class_name: 'Activity', inverse_of: :parent_activity
|
#closed? ⇒ Boolean
400
401
402
|
# File 'app/models/activity.rb', line 400
def closed?
activity_type_id.nil? || activity_result_type_id.present?
end
|
#closed_by ⇒ Party
74
|
# File 'app/models/activity.rb', line 74
belongs_to :closed_by, class_name: 'Party', optional: true
|
90
|
# File 'app/models/activity.rb', line 90
belongs_to :communication, optional: true
|
#compact_notes ⇒ Object
542
543
544
545
|
# File 'app/models/activity.rb', line 542
def compact_notes
d = notes || description
d.gsub(/\[.*\]/, '').strip
end
|
#complete(options = {}) ⇒ Object
532
533
534
535
|
# File 'app/models/activity.rb', line 532
def complete(options = {})
opts = { activity_result_type_id: ActivityResultTypeConstants::CMP, completion_datetime: Time.current }.merge(options)
update(opts)
end
|
#complete? ⇒ Object
Alias for Activity_result_type#complete?
183
|
# File 'app/models/activity.rb', line 183
delegate :complete?, :cancelled?, :result_code, to: :activity_result_type, allow_nil: true
|
343
344
345
346
347
348
349
350
351
352
353
354
|
# File 'app/models/activity.rb', line 343
def contact_options_for_select
p = party
r = resource
return [] unless p || r
skip_persons = activity_type&.party_must_be_company?
skip_organizations = activity_type&.party_must_be_contact?
ContactPoint::AddressBookBuilder.options_for_select(resource: r, party: p, skip_persons:, skip_organizations:)
end
|
#content_for_embedding(_content_type = :primary) ⇒ Object
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
|
# File 'app/models/activity.rb', line 559
def content_for_embedding(_content_type = :primary)
return nil if notes.blank? || notes.length < MIN_EMBEDDABLE_NOTES_LENGTH
parts = []
parts << "Activity: #{activity_type&.task_type || 'Note'}"
parts << "Tags: #{activity_type.tags.join(', ')}" if activity_type&.tags&.any?
parts << "Status: #{result_code || 'Open'}"
parts << "Priority: #{activity_type.priority}" if activity_type&.priority.present?
parts << "Party: #{party&.full_name}" if party
parts << "Customer: #{customer&.full_name}" if customer && customer != party
parts << "Assigned to: #{assigned_resource&.full_name}" if assigned_resource
parts << "Date: #{effective_date.strftime('%B %d, %Y')}" if effective_date
parts << "Due: #{target_datetime.strftime('%B %d, %Y')}" if target_datetime && open?
parts << "Overdue" if overdue?
parts << "Completed: #{completion_datetime.strftime('%B %d, %Y')}" if completion_datetime
parts << "Resource: #{resource_type} ##{resource_id}" if resource_type.present?
parts << "Campaign: #{campaign&.name}" if campaign
parts << compact_notes
parts.compact.join("\n\n")
end
|
77
|
# File 'app/models/activity.rb', line 77
belongs_to :customer, optional: true, inverse_of: :related_activities
|
#default_resource_for_select ⇒ Object
640
641
642
643
644
645
|
# File 'app/models/activity.rb', line 640
def default_resource_for_select
return [] unless resource
formatter = Activity::ResourceList.build_formatter(resource)
[[formatter.display, formatter.identifier]]
end
|
#description ⇒ Object
647
648
649
|
# File 'app/models/activity.rb', line 647
def description
notes.try(:first, 500) || activity_type.try(:description)
end
|
#display_date ⇒ Object
499
500
501
|
# File 'app/models/activity.rb', line 499
def display_date
effective_date.to_s(has_time? ? :crm_default : :crm_date_only)
end
|
#display_type ⇒ Object
404
405
406
|
# File 'app/models/activity.rb', line 404
def display_type
activity_type&.task_type || 'Note'
end
|
#effective_date ⇒ Object
507
508
509
|
# File 'app/models/activity.rb', line 507
def effective_date
completion_datetime || self.target_datetime || created_at
end
|
#effective_origin_date ⇒ Object
308
309
310
|
# File 'app/models/activity.rb', line 308
def effective_origin_date
(original_target_datetime || target_datetime || created_at).to_date
end
|
#embedding_content_changed? ⇒ Boolean
580
581
582
|
# File 'app/models/activity.rb', line 580
def embedding_content_changed?
saved_change_to_notes?
end
|
#has_time? ⇒ Boolean
503
504
505
|
# File 'app/models/activity.rb', line 503
def has_time?
effective_date != effective_date.beginning_of_day
end
|
#historical_open_activities ⇒ ActiveRecord::Relation<HistoricalOpenActivity>
Track each time the activity was left open at end of day
99
|
# File 'app/models/activity.rb', line 99
has_many :historical_open_activities
|
#is_email? ⇒ Object
Alias for Activity_type#is_email?
182
|
# File 'app/models/activity.rb', line 182
delegate :is_email?, to: :activity_type, allow_nil: true
|
#is_note? ⇒ Boolean
511
512
513
|
# File 'app/models/activity.rb', line 511
def is_note?
activity_type_id.nil?
end
|
#is_onsite_service? ⇒ Boolean
521
522
523
524
525
526
|
# File 'app/models/activity.rb', line 521
def is_onsite_service?
activity_type_id == ActivityTypeConstants::ONSITESERVICE or
activity_type_id == ActivityTypeConstants::SSI_INSTALL or
activity_type_id == ActivityTypeConstants::SSFIX_ONSITE_SERVICE or
activity_type_id == ActivityTypeConstants::SGS_ONSITESUPPORT
end
|
#is_service_confirm? ⇒ Boolean
515
516
517
518
519
|
# File 'app/models/activity.rb', line 515
def is_service_confirm?
activity_type_id == ActivityTypeConstants::SERVICECONFIRM or
activity_type_id == ActivityTypeConstants::SSI_PREPLAN_MEET or
activity_type_id == ActivityTypeConstants::SSFIX_SERVICE_CONFIRM
end
|
#is_service_confirm_completed? ⇒ Boolean
749
750
751
752
753
754
755
|
# File 'app/models/activity.rb', line 749
def is_service_confirm_completed?
true if activity_type_id.in?([ActivityTypeConstants::SERVICECONFIRM,
ActivityTypeConstants::SSI_PREPLAN_MEET,
ActivityTypeConstants::SGS_ONSITE_PREPLAN_MEET,
ActivityTypeConstants::SGS_REMOTE_PREPLAN_MEET,
ActivityTypeConstants::SSFIX_SERVICE_CONFIRM]) and activity_result_type_id == ActivityResultTypeConstants::CMP
end
|
736
737
738
739
740
741
742
743
744
745
746
747
|
# File 'app/models/activity.rb', line 736
def is_smartservice_related?
activity_type_id.in?([ActivityTypeConstants::SERVICECONFIRM,
ActivityTypeConstants::ONSITESERVICE,
ActivityTypeConstants::SSI_PREPLAN_MEET,
ActivityTypeConstants::SSI_INSTALL,
ActivityTypeConstants::SGS_ONSITE_PREPLAN_MEET,
ActivityTypeConstants::SGS_REMOTE_PREPLAN_MEET,
ActivityTypeConstants::SGS_ONSITESUPPORT,
ActivityTypeConstants::SGS_REMOTESUPPORT,
ActivityTypeConstants::SSFIX_ONSITE_SERVICE,
ActivityTypeConstants::SSFIX_SERVICE_CONFIRM])
end
|
#lock ⇒ Object
292
293
294
295
296
|
# File 'app/models/activity.rb', line 292
def lock
self.skip_callbacks = true
self.lock_target_datetime = true
save
end
|
#mail_activities ⇒ ActiveRecord::Relation<MailActivity>
98
|
# File 'app/models/activity.rb', line 98
has_many :mail_activities
|
#new_note ⇒ Object
386
387
388
|
# File 'app/models/activity.rb', line 386
def new_note
''
end
|
#new_note=(n) ⇒ Object
376
377
378
379
380
381
382
383
384
|
# File 'app/models/activity.rb', line 376
def new_note=(n)
return if n.blank?
date_stamp = []
date_stamp << Time.current.to_fs(:crm_default)
date_stamp << CurrentScope.user&.show_name_4 if CurrentScope.user && CurrentScope.user.respond_to?(:show_name_4)
self.notes = "[#{date_stamp.compact.join(' ')}]\n#{n}\n#{notes}"
self.description = n&.first(80)
end
|
#open? ⇒ Boolean
396
397
398
|
# File 'app/models/activity.rb', line 396
def open?
!closed?
end
|
92
|
# File 'app/models/activity.rb', line 92
belongs_to :opportunity, inverse_of: :linked_activities, optional: true
|
#original_assigned_resource ⇒ Employee
80
|
# File 'app/models/activity.rb', line 80
belongs_to :original_assigned_resource, class_name: 'Employee', optional: true
|
#overdue? ⇒ Boolean
365
366
367
368
369
370
|
# File 'app/models/activity.rb', line 365
def overdue?
return false if closed?
return false unless target_datetime.present?
(target_datetime < Time.current)
end
|
#parent_activity ⇒ Activity
78
|
# File 'app/models/activity.rb', line 78
belongs_to :parent_activity, class_name: 'Activity', inverse_of: :child_activities, optional: true
|
#parties ⇒ ActiveRecord::Relation<Party>
101
|
# File 'app/models/activity.rb', line 101
has_and_belongs_to_many :parties
|
76
|
# File 'app/models/activity.rb', line 76
belongs_to :party, optional: true
|
#party_name ⇒ Object
392
393
394
|
# File 'app/models/activity.rb', line 392
def party_name
party&.full_name
end
|
#primary_address_id ⇒ Object
491
492
493
|
# File 'app/models/activity.rb', line 491
def primary_address_id
customer.try(:mailing_address_id) || customer.try(:shipping_address_id) || customer.try(:billing_address_id)
end
|
#resource ⇒ Resource
81
|
# File 'app/models/activity.rb', line 81
belongs_to :resource, polymorphic: true, optional: true
|
#resource_combo=(val) ⇒ Object
Backwards-compat: cached browser forms may still submit the old
"ClassName|id" format. Silently convert to GlobalID so
Activity.new(params[:activity]) doesn't blow up.
631
632
633
634
635
636
637
638
|
# File 'app/models/activity.rb', line 631
def resource_combo=(val)
if val.present?
class_name, rid = val.split("|", 2)
self.resource_gid = URI::GID.build(app: GlobalID.app, model_name: class_name, model_id: rid.to_s).to_s
else
self.resource_gid = nil
end
end
|
#resource_gid ⇒ Object
612
613
614
615
616
|
# File 'app/models/activity.rb', line 612
def resource_gid
return unless resource_type.present? && resource_id.present?
URI::GID.build(app: GlobalID.app, model_name: resource_type, model_id: resource_id.to_s).to_s
end
|
#resource_gid=(gid_string) ⇒ Object
618
619
620
621
622
623
624
625
626
|
# File 'app/models/activity.rb', line 618
def resource_gid=(gid_string)
if gid_string.present? && (gid = GlobalID.parse(gid_string))
self.resource_type = gid.model_name
self.resource_id = gid.model_id
else
self.resource_type = nil
self.resource_id = nil
end
end
|
#resource_opportunity ⇒ Opportunity
84
|
# File 'app/models/activity.rb', line 84
belongs_to :resource_opportunity, class_name: 'Opportunity', foreign_key: :resource_id, optional: true
|
#resource_order ⇒ Order
85
|
# File 'app/models/activity.rb', line 85
belongs_to :resource_order, class_name: 'Order', foreign_key: :resource_id, optional: true
|
#resource_quote ⇒ Quote
86
|
# File 'app/models/activity.rb', line 86
belongs_to :resource_quote, class_name: 'Quote', foreign_key: :resource_id, optional: true
|
#resource_room_configuration ⇒ RoomConfiguration
87
|
# File 'app/models/activity.rb', line 87
belongs_to :resource_room_configuration, class_name: 'RoomConfiguration', foreign_key: :resource_id, optional: true
|
88
|
# File 'app/models/activity.rb', line 88
belongs_to :resource_scheduler_booking, class_name: 'SchedulerBooking', foreign_key: :resource_id, optional: true
|
#resource_support_case ⇒ SupportCase
Type-specific resource associations for eager loading (polymorphic can't be preloaded)
83
|
# File 'app/models/activity.rb', line 83
belongs_to :resource_support_case, class_name: 'SupportCase', foreign_key: :resource_id, optional: true
|
#result_code ⇒ Object
Also known as:
activity_result_code
Alias for Activity_result_type#result_code
183
|
# File 'app/models/activity.rb', line 183
delegate :complete?, :cancelled?, :result_code, to: :activity_result_type, allow_nil: true
|
#result_options_for_select ⇒ Object
325
326
327
328
329
|
# File 'app/models/activity.rb', line 325
def result_options_for_select
return unless activity_type
activity_type.result_options_for_select
end
|
#return_to ⇒ Object
339
340
341
|
# File 'app/models/activity.rb', line 339
def return_to
resource || party
end
|
#sales_activity? ⇒ Boolean
304
305
306
|
# File 'app/models/activity.rb', line 304
def sales_activity?
activity_type.try(:sales_activity)
end
|
#sender_for_email_templates ⇒ Object
372
373
374
|
# File 'app/models/activity.rb', line 372
def sender_for_email_templates
assigned_resource || updater || creator
end
|
#sender_party ⇒ Object
For emails, who is the sender?
594
595
596
597
598
599
600
601
602
603
604
605
606
|
# File 'app/models/activity.rb', line 594
def sender_party
primary_rep = party&.customer&.primary_sales_rep
sp = primary_rep if activity_type.sales_rep_as_sender
sp ||= activity_type.sender_party
sp ||= assigned_resource unless assigned_resource_id == self.class.heatwave_assistant_id
sp ||= primary_rep = party.try(:primary_sales_rep)
sp ||= creator if creator.is_a?(Employee)
sp = nil if sp&.id == self.class.heatwave_assistant_id sp ||= Employee.find(105) raise StandardError.new("Unable to determine sender_party for activity id #{id}") unless sp
sp
end
|
#set_assigned_rep ⇒ Object
713
714
715
716
717
718
|
# File 'app/models/activity.rb', line 713
def set_assigned_rep
return true if closed?
self.assigned_resource ||= best_resource_employee
self.original_assigned_resource ||= self.assigned_resource
end
|
#set_campaign ⇒ Object
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
|
# File 'app/models/activity.rb', line 720
def set_campaign
use_campaign = campaign || activity_type&.campaign
return unless use_campaign
return unless (cust = customer)
res = use_campaign.add_customer cust
return unless res.subscribed?
self.campaign = use_campaign
end
|
#set_linked_parties ⇒ Object
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
|
# File 'app/models/activity.rb', line 651
def set_linked_parties
pids = [party_id] if linked_party_ids.present? if linked_party_ids.is_a?(Array)
pids += linked_party_ids
elsif linked_party_ids.is_a?(String)
pids += linked_party_ids.split(',')
end
end
pids += resource.link_party_ids if resource.respond_to?(:link_party_ids) pids = pids.compact.uniq.map(&:to_i)
pids += Contact.where(id: pids).pluck(Arel.sql('distinct customer_id')).compact
pids.uniq!
valid_pids = Party.where(id: pids).pluck(:id)
if valid_pids.size < pids.size
logger.warn(
"Activity#set_linked_parties skipping missing party_ids=#{(pids - valid_pids).join(', ')} " \
"activity_id=#{persisted? ? id : 'new'}"
)
end
pids = valid_pids
return unless pids.present?
unless persisted?
logger.info "Activity (new) linked party ids will become #{pids.join(', ')}"
self.party_ids = pids
return
end
existing_pids = party_ids.to_a
new_pids = pids - existing_pids
return if new_pids.empty?
logger.info "Activity #{id} linked party ids adding #{new_pids.join(', ')} (existing: #{existing_pids.join(', ')})"
new_pids.each do |pid|
self.class.connection.execute(
self.class.sanitize_sql_array([
'INSERT INTO activities_parties (activity_id, party_id) VALUES (?, ?) ON CONFLICT (party_id, activity_id) DO NOTHING',
id, pid
])
)
end
parties.reset
rescue ActiveRecord::RecordNotUnique
logger.info "Activity #{id} set_linked_parties encountered RecordNotUnique - records already exist"
parties.reset
end
|
#target_date ⇒ Object
312
313
314
|
# File 'app/models/activity.rb', line 312
def target_date
target_datetime.nil? ? nil : target_datetime.to_datetime.to_date.to_fs(:crm_default)
end
|
#target_datetime_outside_business_hours? ⇒ Boolean
757
758
759
760
761
762
763
|
# File 'app/models/activity.rb', line 757
def target_datetime_outside_business_hours?
return true unless target_datetime
!(target_datetime - 1.second).in_working_hours?
end
|
#target_time ⇒ Object
316
317
318
319
320
321
322
323
|
# File 'app/models/activity.rb', line 316
def target_time
return unless target_datetime
target_datetime.strftime('%I:%M %P')
end
|
#to_s ⇒ Object
Also known as:
name
482
483
484
485
486
487
488
|
# File 'app/models/activity.rb', line 482
def to_s
[
target_datetime.try(:to_s).try(:crm_date_only),
assigned_resource.try(:name),
activity_type.try(:task_type)
].compact.join(' ')
end
|
#triggered_communications ⇒ ActiveRecord::Relation<Communication>
97
|
# File 'app/models/activity.rb', line 97
has_many :triggered_communications, class_name: 'Communication'
|
#unlock ⇒ Object
298
299
300
301
302
|
# File 'app/models/activity.rb', line 298
def unlock
self.skip_callbacks = true
self.lock_target_datetime = false
save
end
|
#uploads ⇒ ActiveRecord::Relation<Upload>
95
|
# File 'app/models/activity.rb', line 95
has_many :uploads, as: :resource, dependent: :destroy
|
93
|
# File 'app/models/activity.rb', line 93
belongs_to :visit, optional: true
|