Class: SupportCase

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

Overview

== Schema Information

Table name: support_cases
Database name: primary

id :integer not null, primary key
case_number :string not null
case_type :string(255)
closed_at :datetime
closed_reason :string
customer_24h_notification :datetime
description :text
first_review_request_processed :boolean default(FALSE)
first_review_request_processed_date :datetime
mileage :integer
notified_at :datetime
opened_at :datetime
original_case_number :string
preferred_service_timeframe :string
priority :string(255)
reopened_reason :string
review_snoozed_until :datetime
reviewable :boolean default(FALSE)
reviewed :boolean default(FALSE)
service :string
service_date :date
service_duration :integer
service_room_qty :integer
service_time :time
state :string(255)
travel_time :integer
unassigned_notification_sent :boolean default(FALSE), not null
created_at :datetime not null
updated_at :datetime not null
assigned_to_id :integer
creator_id :integer
parent_id :integer
service_address_id :integer
updater_id :integer

Indexes

by_ct_atid (case_type,assigned_to_id)
idx_parent_id (parent_id)
idx_serv_date_case_type_serv_time (service_date,case_type,service_time)
idx_service_address_id (service_address_id)
idx_support_cases_state (state) WHERE (assigned_to_id IS NULL)
index_support_cases_on_case_number (case_number) UNIQUE
index_support_cases_on_state_and_id (state,id)

Foreign Keys

fk_rails_... (parent_id => support_cases.id)
fk_rails_... (service_address_id => addresses.id)

Defined Under Namespace

Classes: Create

Constant Summary collapse

FIELD_TECHNICIAN_CELL =
'12245511225'
REFERENCE_NUMBER_PATTERN =
/^.TK\d+/i
CLOSED_REASONS =
[
  'Answered question',
  'Problem fixed',
  'Stat defaults changed',
  'Damage Repaired Warranty',
  'Damage Repaired Non-Warranty',
  'Heating Product Replaced Warranty',
  'Heating Product Replaced Non-Warranty',
  'Customer Waiting for Other Parties',
  'Customer Decided to Abandon the System',
  "Customer Doesn't Respond",
  'Duplicate'
].freeze
SERVICE_CLOSED_REASONS =
[
  'Service has been completed',
  'Service has been completed - warranty claim - free service',
  'Service has not been completed - no show / no refund',
  'Service has not been completed - cancelled within the 24h grace period',
  'Service has not been completed - not able to perform due to comply with T&C',
  'Duplicate',
  "Customer Doesn't Respond"
].freeze
PRIORITIES_HASH =
{
  Low: { label: 'Low (within 1 business day)', follow_up_delay: 7 },
  Medium: { label: 'Medium (within 2 hours)', follow_up_delay: 3 },
  High: { label: 'High (within 20 minutes)', follow_up_delay: 1 }
}.freeze
SMART_SERVICES_COLORS =
{ SMARTFIT_RES_INDOOR_FIXRATE: '#f0ad4e',
SMARTFIT_RES_OUTDOOR_FIXRATE: '#d7d7d7',
SMARTFIT_COM_INDOOR_FIXRATE1: '#d9534f',
SMARTFIT_COM_OUTDOOR_FIXRATE1: '#94E994',
ONSITESERVICE: '#6ABA5A',
CALLCONFIRM: '#f0ad4e' }.freeze
LOCKED_STATES =
%i[open closed waiting_on_customer waiting_to_confirm_appointment pending_service_payment site_visit_scheduled
third_party_site_visit_scheduled waiting_on_accountant waiting_on_warmlyyours sent_to_collections].freeze

Constants included from Models::Auditable

Models::Auditable::ALWAYS_IGNORED

Instance Attribute Summary collapse

Belongs to collapse

Methods included from Models::Auditable

#creator, #updater

Has and belongs to many collapse

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::EventPublishable

#publish_event

Instance Attribute Details

#case_typeObject (readonly)



129
# File 'app/models/support_case.rb', line 129

validates :description, :case_type, :priority, presence: true

#descriptionObject (readonly)



129
# File 'app/models/support_case.rb', line 129

validates :description, :case_type, :priority, presence: true

#order_idObject

Returns the value of attribute order_id.



137
138
139
# File 'app/models/support_case.rb', line 137

def order_id
  @order_id
end

#priorityObject (readonly)



129
# File 'app/models/support_case.rb', line 129

validates :description, :case_type, :priority, presence: true

#service_creation_optionObject

Returns the value of attribute service_creation_option.



137
138
139
# File 'app/models/support_case.rb', line 137

def service_creation_option
  @service_creation_option
end

Class Method Details

.case_type_for_search_selectObject



275
276
277
# File 'app/models/support_case.rb', line 275

def self.case_type_for_search_select
  %w[Tech Accounting Ecommerce SmartService].map { |ct| [ct, ct] }
end

.case_type_for_selectObject



271
272
273
# File 'app/models/support_case.rb', line 271

def self.case_type_for_select
  %w[Tech Accounting Ecommerce SmartService].map { |ct| [ct, ct] }
end

.case_typesObject



233
234
235
# File 'app/models/support_case.rb', line 233

def self.case_types
  %w[Tech Accounting Ecommerce]
end

.closed_casesActiveRecord::Relation<SupportCase>

A relation of SupportCases that are closed cases. Active Record Scope

Returns:

See Also:



142
# File 'app/models/support_case.rb', line 142

scope :closed_cases, -> { where(state: %w[closed]) }

.lockedActiveRecord::Relation<SupportCase>

A relation of SupportCases that are locked. Active Record Scope

Returns:

See Also:



146
# File 'app/models/support_case.rb', line 146

scope :locked, -> { where(state: LOCKED_STATES) }

.lookupActiveRecord::Relation<SupportCase>

A relation of SupportCases that are lookup. Active Record Scope

Returns:

See Also:



139
# File 'app/models/support_case.rb', line 139

scope :lookup, ->(q) { where(SupportCase[:case_number].matches("#{q}%")) }

.not_closed_casesActiveRecord::Relation<SupportCase>

A relation of SupportCases that are not closed cases. Active Record Scope

Returns:

See Also:



148
# File 'app/models/support_case.rb', line 148

scope :not_closed_cases, -> { open_cases + waiting_cases }

.open_casesActiveRecord::Relation<SupportCase>

A relation of SupportCases that are open cases. Active Record Scope

Returns:

See Also:



141
# File 'app/models/support_case.rb', line 141

scope :open_cases, -> { where(state: %w[new open]) }

.pending_service_paymentActiveRecord::Relation<SupportCase>

A relation of SupportCases that are pending service payment. Active Record Scope

Returns:

See Also:



147
# File 'app/models/support_case.rb', line 147

scope :pending_service_payment, -> { where(state: %w[pending_service_payment]) }

.priorities_for_selectObject



283
284
285
# File 'app/models/support_case.rb', line 283

def self.priorities_for_select
  PRIORITIES_HASH.map { |ph_k, ph_sh| [ph_sh[:label], ph_k.to_s] }
end

.service_creation_optionsObject



619
620
621
622
# File 'app/models/support_case.rb', line 619

def self.service_creation_options
  [['Create a new support case', 'new_support_case'], ['Use existing support sase', 'existing_support_case'],
   ["Don't create a support case", 'skip_support_case']]
end

.servicesActiveRecord::Relation<SupportCase>

A relation of SupportCases that are services. Active Record Scope

Returns:

See Also:



140
# File 'app/models/support_case.rb', line 140

scope :services, -> { where(case_type: %w[SmartService SmartInstall SmartSupport SmartFix]) }

.states_for_selectObject



279
280
281
# File 'app/models/support_case.rb', line 279

def self.states_for_select
  state_machines[:state].states.map { |s| [s.human_name, s.value] }
end

.waiting_casesActiveRecord::Relation<SupportCase>

A relation of SupportCases that are waiting cases. Active Record Scope

Returns:

See Also:



143
144
145
# File 'app/models/support_case.rb', line 143

scope :waiting_cases, -> {
  where(state: %w[waiting_on_customer pending_service_payment waiting_to_confirm_appointment site_visit_scheduled waiting_on_equipment site_visit_scheduled third_party_site_visit_scheduled waiting_on_accountant waiting_on_warmlyyours])
}

Instance Method Details

#activitiesActiveRecord::Relation<Activity>

Returns:

See Also:



113
# File 'app/models/support_case.rb', line 113

has_many :activities, as: :resource, dependent: :destroy

#advance_follow_up_activityObject

When another activity occurs, we need to advance the tickout activity



482
483
484
485
486
487
488
489
490
491
# File 'app/models/support_case.rb', line 482

def advance_follow_up_activity
  return unless (tickout = activities.open_activities.find_by(activity_type_id: ActivityTypeConstants::TICKOUT))

  tickout.target_datetime = follow_up_delay.working.days.from_now
  tickout.assigned_resource = assigned_to
  tickout.lock_target_datetime = true
  tickout.party ||= support_case_participants.first&.party
  tickout.save
  tickout
end

#all_credit_memosObject



299
300
301
302
# File 'app/models/support_case.rb', line 299

def all_credit_memos
  all_credit_memo_ids = ([] + order_credit_memo_ids + credit_memo_ids).compact.uniq
  CreditMemo.where(id: all_credit_memo_ids)
end

#all_participantsObject



502
503
504
# File 'app/models/support_case.rb', line 502

def all_participants
  support_case_participants.with_party.map { |scp| scp.party.full_name }.join(', ')
end

#all_rmasObject



304
305
306
307
# File 'app/models/support_case.rb', line 304

def all_rmas
  all_rma_ids = ([] + rma_ids + order_rma_ids).compact.uniq
  Rma.where(id: all_rma_ids)
end

#assigned_toEmployee

Returns:

See Also:



105
# File 'app/models/support_case.rb', line 105

belongs_to :assigned_to, class_name: 'Employee', optional: true

#assigned_to_nameObject



213
214
215
# File 'app/models/support_case.rb', line 213

def assigned_to_name
  assigned_to.nil? ? 'Unassigned' : assigned_to.full_name
end

#assignment_email_urlObject



343
344
345
# File 'app/models/support_case.rb', line 343

def assignment_email_url
  SUPPORT_CASE_CRM_BASE_URL + id.to_s
end

#build_activityObject



291
292
293
# File 'app/models/support_case.rb', line 291

def build_activity
  activities.build resource: self, party: support_case_participants.with_party.first&.party
end

#build_new_participant(np) ⇒ Object

Build an unsaved participant with a new Contact party when the caller
isn't in the system yet (e.g. phone popup for an unknown number). The
SupportCaseParticipant#set_party callback turns the virtual
party_name / contact_name into a real Customer / Contact on save.



392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
# File 'app/models/support_case.rb', line 392

def build_new_participant(np)
  new_party = Contact.new
  new_party.contact_points.build(category: ContactPoint::EMAIL)
  new_party.contact_points.build(category: ContactPoint::CELL)
  new_party.contact_points.build(category: ContactPoint::PHONE, detail: np[:phone].presence)
  new_party.contact_points.build(category: ContactPoint::FAX)

  support_case_participants.build(
    party: new_party,
    party_name: np[:party_name].presence,
    contact_name: np[:contact_name].presence,
    role: np[:role].presence || 'homeowner',
    preferred_language: np[:preferred_language].presence
  )
end

#build_participants_and_rooms(params) ⇒ Object



347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
# File 'app/models/support_case.rb', line 347

def build_participants_and_rooms(params)
  if params[:new_participant].present?
    build_new_participant(params[:new_participant])
    return
  end

  if params[:participant_id]
    party = Party.find(params[:participant_id])
  elsif params[:room_configuration_id]
    rc = RoomConfiguration.find(params[:room_configuration_id])
    party = rc.customer
    self.room_configuration_ids = [params[:room_configuration_id]]
  elsif params[:order_id]
    ord = Order.find(params[:order_id])
    party = ord.customer
    contact = ord.contact
    self.room_configuration_ids = ord.room_configuration_ids if ord.room_configuration_ids.any?
    self.order_ids = [ord.id]
    # In this case we'll have the contact and the customer as participants.
    if contact.present?
      support_case_participants.build(party: contact,
                                      email: contact.contact_points.emails.first,
                                      phone: contact.contact_points.voice_callable.first,
                                      role: 'homeowner',
                                      preferred_language: contact.preferred_language)
    end
  elsif params[:quote_id]
    quo = Quote.find(params[:quote_id])
    party = quo.customer
    self.room_configuration_ids += quo.room_configuration_ids
    self.quote_ids = [quo.id]
  end
  return unless party.present?

  support_case_participants.build(party: party,
                                  email: party.contact_points.emails.first,
                                  phone: party.contact_points.voice_callable.first,
                                  role: 'homeowner',
                                  preferred_language: party.preferred_language)
end

#close_tickoutObject



493
494
495
496
497
498
499
500
# File 'app/models/support_case.rb', line 493

def close_tickout
  activities.open_activities.where('activity_type_id = ?', ActivityTypeConstants::TICKOUT).find_each do |a|
    a.halt_chain = true
    a.completion_datetime = Time.current
    a.activity_result_type_id = ActivityResultTypeConstants::CANCEL
    a.save
  end
end

#communication_template_system_codeObject



534
535
536
537
538
539
540
541
542
543
# File 'app/models/support_case.rb', line 534

def communication_template_system_code
  case case_type
  when 'Accounting'
    'ACCT_TCKT_UPDATE'
  when 'Ecommerce'
    'ECOM_TCKT_UPDATE'
  else
    'SUPPORTCASE_UPDATE'
  end
end

#communicationsActiveRecord::Relation<Communication>

Returns:

See Also:



114
# File 'app/models/support_case.rb', line 114

has_many :communications, as: :resource, dependent: :nullify

#company_review_urlObject

Reviews.io dynamic link for company review using the case number as order_id



625
626
627
# File 'app/models/support_case.rb', line 625

def company_review_url
  Api::ReviewsIo::DynamicLinkBuilder.for_support_case(self)
end

#convert_to_stkObject



643
644
645
646
647
648
649
650
651
652
653
654
655
# File 'app/models/support_case.rb', line 643

def convert_to_stk
  res = false
  if case_number.include?('TTK')
    self.original_case_number = case_number
    case_number.sub!('TTK', 'STK')
    self.case_type = 'SmartService'
    self.state = 'pending_service_payment'
    self.assigned_to_id = Employee::SCOTT
    res = save
    converted_from_ttk_to_stk_activity
  end
  res
end

#converted_from_ttk_to_stk_activityObject



657
658
659
660
# File 'app/models/support_case.rb', line 657

def converted_from_ttk_to_stk_activity
  Activity.create(resource: self,
                  notes: 'Support Case converted from TTK to STK.')
end

#create_follow_up_activityObject



470
471
472
473
474
475
476
477
478
479
# File 'app/models/support_case.rb', line 470

def create_follow_up_activity
  # unless you've already got one
  Activity.create(lock_target_datetime: true,
                  activity_type_id: ActivityTypeConstants::TICKOUT,
                  target_datetime: follow_up_delay.working.days.from_now,
                  assigned_resource: assigned_to,
                  party: support_case_participants.first&.party,
                  resource: self,
                  notes: "Follow up on Support Case #{case_number}.")
end

#create_initial_service_activityObject



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/support_case.rb', line 408

def create_initial_service_activity
  order = orders.contains_service_items.first # The first order is the one who initiated the service case
  return unless order.present?

  if order.is_smartfit_service?
    first_activity = ActivityTypeConstants::SERVICECONFIRM
  elsif order.is_smartinstall_service?
    first_activity = ActivityTypeConstants::SSI_PREPLAN_MEET
  elsif order.is_smartfix_service?
    first_activity = ActivityTypeConstants::SSFIX_SERVICE_CONFIRM
  elsif order.is_smartguide_service?
    first_activity = if order.line_items.joins(:item).merge(Item.where(sku: 'SGS_ONSITE_FIXRATE')).any?
                       ActivityTypeConstants::SGS_ONSITE_PREPLAN_MEET
                     else
                       ActivityTypeConstants::SGS_REMOTE_PREPLAN_MEET
                     end
  end

  Activity.create(lock_target_datetime: false,
                  activity_type_id: first_activity,
                  target_datetime: 1.working.days.from_now,
                  assigned_resource: Employee.find_by(id: 82), # Assigned by default to Scott
                  party: order.customer,
                  resource: self,
                  notes: 'Call Customer to confirm date and time of the service.')

  InternalMailer.smart_service_requested_notification(self).deliver_later
end

#create_new_tickout(note) ⇒ Object



662
663
664
665
666
667
668
669
670
# File 'app/models/support_case.rb', line 662

def create_new_tickout(note)
  Activity.create(lock_target_datetime: true,
                  activity_type_id: ActivityTypeConstants::TICKOUT,
                  target_datetime: 0.working.days.from_now,
                  assigned_resource: assigned_to,
                  party: support_case_participants.with_party.first&.party,
                  resource: self,
                  notes: "Case reopened. Reason: #{note}")
end

#credit_memosActiveRecord::Relation<CreditMemo>

Returns:

See Also:



118
# File 'app/models/support_case.rb', line 118

has_many :credit_memos

#customerObject



237
238
239
# File 'app/models/support_case.rb', line 237

def customer
  support_case_participants.with_party.detect { |sc| sc.party&.customer }&.party&.customer
end

#customer_addressObject



253
254
255
256
257
# File 'app/models/support_case.rb', line 253

def customer_address
  return unless service_address_id

  ApplicationController.helpers.format_for_display service_address, { address_type: false, include_recipient: false }
end

#customer_emailObject



263
264
265
# File 'app/models/support_case.rb', line 263

def customer_email
  customer.try(:email) || 'unspecified'
end

#customer_full_nameObject



245
246
247
# File 'app/models/support_case.rb', line 245

def customer_full_name
  customer.try(:full_name) || 'unspecified'
end

#customer_phoneObject



249
250
251
# File 'app/models/support_case.rb', line 249

def customer_phone
  customer.try(:phone) || 'unspecified'
end

#customer_reference_numberObject



241
242
243
# File 'app/models/support_case.rb', line 241

def customer_reference_number
  customer.try(:reference_number) || 'unspecified'
end

#editing_locked?Boolean

Returns:

  • (Boolean)


561
562
563
# File 'app/models/support_case.rb', line 561

def editing_locked?
  LOCKED_STATES.include?(state.to_sym)
end

#events_for_selectObject



287
288
289
# File 'app/models/support_case.rb', line 287

def events_for_select
  state_events.select { |evt| send(:"can_#{evt}?") }.sort.map { |evt| [evt.to_s.titleize, evt] }
end

#field_technician_cellObject

In the future with more than one tech we can change this method



209
210
211
# File 'app/models/support_case.rb', line 209

def field_technician_cell
  FIELD_TECHNICIAN_CELL
end

#formatted_service_timeObject



464
465
466
467
468
# File 'app/models/support_case.rb', line 464

def formatted_service_time
  service_time.strftime('%l:%M %p')
rescue StandardError
  nil
end

#generate_service_calendar_eventObject



437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
# File 'app/models/support_case.rb', line 437

def generate_service_calendar_event
  return nil if service_date.nil? || service_time.nil?

  require 'icalendar'
  require 'icalendar/tzinfo'
  cal = Icalendar::Calendar.new
  event_start = DateTime.new service_date.year, service_date.month, service_date.day, service_time.hour, service_time.min, service_time.sec
  event_end = DateTime.new service_date.year, service_date.month, service_date.day, service_time.hour + 3, service_time.min, service_time.sec

  # create PTO block in JL calendar
  Employee.find(Employee::SCOTT).employee_events.new(status: 'working_on_service', date: event_start.to_date, from_hour: event_start.to_time,
                                                     to_hour: event_end.to_time, authorized: true).save

  tzid = 'America/Chicago'
  tz = TZInfo::Timezone.get tzid
  timezone = tz.ical_timezone event_start
  cal.add_timezone timezone

  cal.event do |e|
    e.dtstart = Icalendar::Values::DateTime.new event_start, 'tzid' => tzid
    e.dtend   = Icalendar::Values::DateTime.new event_end, 'tzid' => tzid
    e.summary = "WarmlyYours Onsite Service #{case_number}"
    e.description = 'If you want to change or cancel this appointment, please contact WarmlyYours at 800-875-5285.'
  end
  cal
end

#is_accounting?Boolean

Returns:

  • (Boolean)


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

def is_accounting?
  case_type == 'Accounting'
end

#is_ecommerce?Boolean

Returns:

  • (Boolean)


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

def is_ecommerce?
  case_type == 'Ecommerce'
end

#is_service?Boolean

Returns:

  • (Boolean)


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

def is_service?
  case_type == 'SmartService'
end

#is_tech?Boolean

Returns:

  • (Boolean)


217
218
219
# File 'app/models/support_case.rb', line 217

def is_tech?
  case_type == 'Tech'
end

Use for activity callback



327
328
329
# File 'app/models/support_case.rb', line 327

def link_party_ids
  support_case_participants.with_party.pluck(:party_id)
end

#linked_casesActiveRecord::Relation<SupportCase>

Returns:

See Also:



120
# File 'app/models/support_case.rb', line 120

has_many :linked_cases, class_name: 'SupportCase', foreign_key: 'parent_id'

#nameObject



331
332
333
# File 'app/models/support_case.rb', line 331

def name
  "Ticket #{case_number}"
end

#order_credit_memosActiveRecord::Relation<CreditMemo>

Returns:

See Also:



119
# File 'app/models/support_case.rb', line 119

has_many :order_credit_memos, class_name: 'CreditMemo', through: :orders, source: :credit_memos

#order_rmasActiveRecord::Relation<Rma>

Returns:

  • (ActiveRecord::Relation<Rma>)

See Also:



117
# File 'app/models/support_case.rb', line 117

has_many :order_rmas, class_name: 'Rma', through: :orders, source: :rmas

#ordersActiveRecord::Relation<Order>

Returns:

  • (ActiveRecord::Relation<Order>)

See Also:



109
# File 'app/models/support_case.rb', line 109

has_and_belongs_to_many :orders, validate: false

#participants_options_for_selectObject



514
515
516
# File 'app/models/support_case.rb', line 514

def participants_options_for_select
  support_case_participants.with_party.map { |scp| [scp.party.full_name, scp.party_id] }
end

#primary_partyObject



295
296
297
# File 'app/models/support_case.rb', line 295

def primary_party
  support_case_participants.with_party.first&.party
end

#project_nameObject



545
546
547
# File 'app/models/support_case.rb', line 545

def project_name
  orders.first&.opportunity&.name || room_configurations.first&.opportunity&.name
end

#quotesActiveRecord::Relation<Quote>

Returns:

  • (ActiveRecord::Relation<Quote>)

See Also:



110
# File 'app/models/support_case.rb', line 110

has_and_belongs_to_many :quotes, validate: false

#reviews_io_reviewsObject

Find Reviews.io reviews linked to this support case (by case_number as order_id)



630
631
632
633
634
# File 'app/models/support_case.rb', line 630

def reviews_io_reviews
  identifiers = [case_number]
  identifiers << customer&.reference_number if customer.present?
  ReviewsIo.active.store_reviews.where(order_id: identifiers.compact).recent
end

#rmasActiveRecord::Relation<Rma>

Returns:

  • (ActiveRecord::Relation<Rma>)

See Also:



116
# File 'app/models/support_case.rb', line 116

has_many :rmas

#room_configurationsActiveRecord::Relation<RoomConfiguration>

Returns:

  • (ActiveRecord::Relation<RoomConfiguration>)

See Also:



108
# File 'app/models/support_case.rb', line 108

has_and_belongs_to_many :room_configurations, validate: false

#selection_nameObject



339
340
341
# File 'app/models/support_case.rb', line 339

def selection_name
  "#{case_number} - #{case_type} - #{human_state_name}"
end

#send_24h_customer_notificationObject



587
588
589
590
591
592
# File 'app/models/support_case.rb', line 587

def send_24h_customer_notification
  smartservice_reminder(ActivityTypeConstants::ONSITESERVICE, 'SMARTFIT_APPOINTMENT_REMINDER')
  smartservice_reminder(ActivityTypeConstants::SSI_INSTALL, 'SMARTINSTALL_APPOINTMENT_REMINDER')
  smartservice_reminder(ActivityTypeConstants::SGS_ONSITESUPPORT, 'SMARTSUPPORT_APPOINTMENT_REMINDER')
  smartservice_reminder(ActivityTypeConstants::SGS_REMOTESUPPORT, 'SMARTSUPPORT_APPOINTMENT_REMINDER')
end

#send_unassigned_emailObject



518
519
520
521
# File 'app/models/support_case.rb', line 518

def send_unassigned_email
  CommunicationBuilder.new(resource: self, template_system_code: unassigned_ticket_system_code).create
  update(unassigned_notification_sent: true)
end

#service_addressAddress

Returns:

See Also:



106
# File 'app/models/support_case.rb', line 106

belongs_to :service_address, class_name: 'Address', optional: true

#service_priceObject



549
550
551
# File 'app/models/support_case.rb', line 549

def service_price
  orders.first.total
end

#service_total_priceObject



267
268
269
# File 'app/models/support_case.rb', line 267

def service_total_price
  ActionController::Base.helpers.number_to_currency(service_price)
end

#smart_service_all_day?Boolean

Returns:

  • (Boolean)


565
566
567
# File 'app/models/support_case.rb', line 565

def smart_service_all_day?
  service_time.blank?
end

#smart_service_calendar_colorObject



553
554
555
556
557
558
559
# File 'app/models/support_case.rb', line 553

def smart_service_calendar_color
  if activities.where(activity_type_id: ActivityTypeConstants::ONSITESERVICE, activity_result_type_id: nil).any?
    SupportCase::SMART_SERVICES_COLORS[:ONSITESERVICE]
  else
    SupportCase::SMART_SERVICES_COLORS[:CALLCONFIRM]
  end
end

#smart_service_end_timeObject



579
580
581
582
583
584
585
# File 'app/models/support_case.rb', line 579

def smart_service_end_time
  (service_date.to_s + ' ' + (begin
    service_time + 3.hours
  rescue StandardError
    nil
  end).to_s).to_datetime&.strftime('%FT%T')
end

#smart_service_scheduleObject



569
570
571
572
573
# File 'app/models/support_case.rb', line 569

def smart_service_schedule
  return nil unless service_date.present? && preferred_service_timeframe.present?

  "#{service_date.strftime('%b %d, %Y')} - #{preferred_service_timeframe.titleize} frame"
end

#smart_service_start_timeObject



575
576
577
# File 'app/models/support_case.rb', line 575

def smart_service_start_time
  "#{service_date} #{service_time}".to_datetime&.strftime('%FT%T')
end

#smartservice_reminder(activity_type, email_template) ⇒ Object



594
595
596
597
598
599
600
601
602
603
604
605
606
# File 'app/models/support_case.rb', line 594

def smartservice_reminder(activity_type, email_template)
  return unless ss_activity = activities.where(activity_type_id: activity_type).last

  sender_party = ss_activity.sender_party

  CommunicationBuilder.new(resource: self,
                           sender_party: sender_party,
                           recipient_party: ss_activity.customer,
                           current_user: sender_party,
                           use_best_email: true,
                           template: EmailTemplate.find_by(system_code: email_template)).create
  update(customer_24h_notification: Time.current)
end

#sms_enabled_numbersObject



506
507
508
# File 'app/models/support_case.rb', line 506

def sms_enabled_numbers
  ContactPoint.joins(party: :support_case_participants).merge(support_case_participants).sms_numbers.order(:detail).map(&:formatted_for_sms).uniq
end

#sms_messagesObject



510
511
512
# File 'app/models/support_case.rb', line 510

def sms_messages
  SmsMessage.for_numbers(sms_enabled_numbers)
end

#suggested_participantsObject



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
# File 'app/models/support_case.rb', line 309

def suggested_participants
  parties = []
  room_configurations.each do |rc|
    parties << rc.customer
    parties.concat(rc.customer.contacts)
  end
  support_case_participants.with_party.each do |scp|
    unless scp.party.nil?
      parties << scp.party
      parties.concat(scp.party.contacts)
    end
  end
  # Reject parties already in
  parties = parties.reject { |p| p.inactive || support_case_participants.with_party.any? { |scp| scp.party_id == p.id } }
  parties.compact.uniq
end

#support_case_participantsActiveRecord::Relation<SupportCaseParticipant>

Returns:

See Also:



112
# File 'app/models/support_case.rb', line 112

has_many :support_case_participants, inverse_of: :support_case

#to_sObject



335
336
337
# File 'app/models/support_case.rb', line 335

def to_s
  "Support Case # #{case_number}"
end

#tracking_email_addressObject



636
637
638
639
640
641
# File 'app/models/support_case.rb', line 636

def tracking_email_address
  domain = Rails.application.config.x.email_domain
  prefix = 'support'
  encrypted_id = Encryption.encrypt_string(id.to_s)
  "#{prefix}+id#{encrypted_id}@#{domain}"
end

#unassigned_ticket_system_codeObject



523
524
525
526
527
528
529
530
531
532
# File 'app/models/support_case.rb', line 523

def unassigned_ticket_system_code
  case case_type
  when 'Accounting'
    'ACCT_TCKT_UNASSIGNED'
  when 'Ecommerce'
    'ECOM_TCKT_UNASSIGNED'
  else
    'SUPPORTCASE_UNASSGND'
  end
end

#uploadsActiveRecord::Relation<Upload>

Returns:

  • (ActiveRecord::Relation<Upload>)

See Also:



115
# File 'app/models/support_case.rb', line 115

has_many :uploads, as: :resource, dependent: :destroy

#versions_for_audit_trail(_params = {}) ⇒ Object



608
609
610
611
612
613
614
615
616
617
# File 'app/models/support_case.rb', line 608

def versions_for_audit_trail(_params = {})
  query_sql = %q{
                (item_type = 'SupportCase' and item_id = :id)
                OR (
                  item_type = 'SupportCaseParticipant'
                    AND reference_data @> '{"party_id": :id}'
                )
              }
  RecordVersion.where(query_sql, id: id)
end