Class: Praise

Inherits:
ApplicationRecord show all
Includes:
Models::Auditable
Defined in:
app/models/praise.rb

Overview

== Schema Information

Table name: praises
Database name: primary

id :integer not null, primary key
description :text
headline :string
image_mime_type :string
image_name :string
image_size :integer
image_uid :string
notify :boolean default(FALSE), not null
notify_staff :boolean default(FALSE), not null
praise :text
praise_date :date
praise_type :integer default("customer_praise")
private :boolean default(FALSE)
publish_on :datetime
published_at :datetime
rank :integer
source :string
state :string default("draft"), not null
created_at :datetime not null
updated_at :datetime not null
creator_id :integer
employee_record_id :integer
originating_employee_record_id :integer
originating_party_id :integer
updater_id :integer

Indexes

idx_praises_state (state)
index_praises_on_employee_record_id (employee_record_id)
index_praises_on_originating_party_id (originating_party_id)
index_praises_on_praise_date (praise_date)
praises_originating_employee_record_id_idx (originating_employee_record_id)

Foreign Keys

fk_rails_... (originating_employee_record_id => employee_records.id)
fk_rails_... (originating_party_id => parties.id)

Constant Summary

Constants included from Models::Auditable

Models::Auditable::ALWAYS_IGNORED

Instance Attribute Summary collapse

Has many collapse

Belongs to collapse

Methods included from Models::Auditable

#creator, #updater

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

#created_at_overrideObject

Returns the value of attribute created_at_override.



67
68
69
# File 'app/models/praise.rb', line 67

def created_at_override
  @created_at_override
end

#employee_record_idsObject (readonly)



70
# File 'app/models/praise.rb', line 70

validates :rank, :image, :employee_record_ids, presence: { if: :is_a_sales_award? }

#headlineObject (readonly)



71
# File 'app/models/praise.rb', line 71

validates :headline, :employee_record_ids, :praise_date, presence: { if: :award? }

#imageObject (readonly)



70
# File 'app/models/praise.rb', line 70

validates :rank, :image, :employee_record_ids, presence: { if: :is_a_sales_award? }

#praise_dateObject (readonly)



69
# File 'app/models/praise.rb', line 69

validates :praise_type, :praise_date, presence: true

#praise_typeObject (readonly)



69
# File 'app/models/praise.rb', line 69

validates :praise_type, :praise_date, presence: true

#rankObject (readonly)



70
# File 'app/models/praise.rb', line 70

validates :rank, :image, :employee_record_ids, presence: { if: :is_a_sales_award? }

#updated_at_overrideObject

Returns the value of attribute updated_at_override.



67
68
69
# File 'app/models/praise.rb', line 67

def updated_at_override
  @updated_at_override
end

Class Method Details

.awardsActiveRecord::Relation<Praise>

A relation of Praises that are awards. Active Record Scope

Returns:

  • (ActiveRecord::Relation<Praise>)

See Also:



83
# File 'app/models/praise.rb', line 83

scope :awards, -> { where(praise_type: [Praise.praise_types[:monthly_sales_award], Praise.praise_types[:yearly_sales_award], Praise.praise_types[:award]]).order('praises.praise_date desc') }

.awards_for_selectObject



123
124
125
126
127
128
129
130
131
132
133
134
# File 'app/models/praise.rb', line 123

def self.awards_for_select
  %w[million_dollar_club
     oustanding_dependability
     attitude_is_everything
     on_time_delivery
     make_a_positive_difference
     most_innovative
     mountain_mover
     employee_of_the_year
     most_shoutouts
     peoples_choice].sort.map(&:titleize)
end

.due_to_publishActiveRecord::Relation<Praise>

A relation of Praises that are due to publish. Active Record Scope

Returns:

  • (ActiveRecord::Relation<Praise>)

See Also:



81
# File 'app/models/praise.rb', line 81

scope :due_to_publish, -> { scheduled.where(Praise[:publish_on].lteq(Time.current)).order(:publish_on) }

.praise_types_for_selectObject



140
141
142
# File 'app/models/praise.rb', line 140

def self.praise_types_for_select
  Praise.praise_types.sort.map { |name, value| [name.humanize, value] }
end

.praisesActiveRecord::Relation<Praise>

A relation of Praises that are praises. Active Record Scope

Returns:

  • (ActiveRecord::Relation<Praise>)

See Also:



84
# File 'app/models/praise.rb', line 84

scope :praises, -> { where(praise_type: [Praise.praise_types[:employee_praise], Praise.praise_types[:customer_praise]]).order('praises.praise_date desc') }

.public_praisesActiveRecord::Relation<Praise>

A relation of Praises that are public praises. Active Record Scope

Returns:

  • (ActiveRecord::Relation<Praise>)

See Also:



85
# File 'app/models/praise.rb', line 85

scope :public_praises, -> { where(private: false) }

.publish_scheduled_praisesObject



136
137
138
# File 'app/models/praise.rb', line 136

def self.publish_scheduled_praises
  Praise.due_to_publish.each(&:publish)
end

.publishedActiveRecord::Relation<Praise>

A relation of Praises that are published. Active Record Scope

Returns:

  • (ActiveRecord::Relation<Praise>)

See Also:



79
# File 'app/models/praise.rb', line 79

scope :published, -> { where(state: 'published') }

.recent_praisesActiveRecord::Relation<Praise>

A relation of Praises that are recent praises. Active Record Scope

Returns:

  • (ActiveRecord::Relation<Praise>)

See Also:



82
# File 'app/models/praise.rb', line 82

scope :recent_praises, -> { published.order('praises.published_at DESC, praises.praise_date DESC, praises.created_at DESC') }

.scheduledActiveRecord::Relation<Praise>

A relation of Praises that are scheduled. Active Record Scope

Returns:

  • (ActiveRecord::Relation<Praise>)

See Also:



80
# File 'app/models/praise.rb', line 80

scope :scheduled, -> { where(state: 'scheduled').where.not(publish_on: nil) }

.states_for_selectObject



144
145
146
# File 'app/models/praise.rb', line 144

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

Instance Method Details

#appraisalsActiveRecord::Relation<Appraisal>

The employee this praise is for

Returns:

See Also:



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

has_many :appraisals

#employee_recordsActiveRecord::Relation<EmployeeRecord>

Returns:

See Also:



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

has_many :employee_records, through: :appraisals

#events_for_selectObject



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

def events_for_select
  [["#{human_state_name.titleize} (Current)", '']] + possible_events_for_select
end

#fudge_timestampsObject



250
251
252
253
254
255
256
257
# File 'app/models/praise.rb', line 250

def fudge_timestamps
  attrs = {}
  attrs[:updated_at] = updated_at_override if updated_at_override.present?
  attrs[:created_at] = created_at_override if created_at_override.present?
  return unless attrs.present?

  update_columns attrs
end

#is_a_praise?Boolean

Returns:

  • (Boolean)


166
167
168
# File 'app/models/praise.rb', line 166

def is_a_praise?
  praise_type =~ /praise/
end

#is_a_sales_award?Boolean

Returns:

  • (Boolean)


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

def is_a_sales_award?
  praise_type =~ /sales_award/
end

#notify?Boolean

Returns:

  • (Boolean)


148
149
150
# File 'app/models/praise.rb', line 148

def notify?
  notify.to_b
end

#notify_staff?Boolean

Returns:

  • (Boolean)


152
153
154
# File 'app/models/praise.rb', line 152

def notify_staff?
  notify_staff.to_b
end

#originating_employee_recordEmployeeRecord



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

belongs_to :originating_employee_record, class_name: 'EmployeeRecord', optional: true

#originating_partyParty

The person giving the praise, customer, employee or contact

Returns:

See Also:



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

belongs_to :originating_party, class_name: 'Party', optional: true

#possible_eventsObject



259
260
261
# File 'app/models/praise.rb', line 259

def possible_events
  state_transitions.map(&:event).sort
end

#possible_events_for_selectObject



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

def possible_events_for_select
  possible_events.map { |evt| [evt.to_s.titleize, evt] }
end

#ready_to_publish?Boolean

Returns:

  • (Boolean)


156
157
158
# File 'app/models/praise.rb', line 156

def ready_to_publish?
  publish_on.nil? || publish_on <= Time.current
end

#recipient_nameObject



232
233
234
235
236
237
238
# File 'app/models/praise.rb', line 232

def recipient_name
  if employee_records.any?
    employee_records.map { |e| e.party.full_name }.join(', ')
  else
    'WarmlyYours'
  end
end

#send_notificationObject



160
161
162
163
164
# File 'app/models/praise.rb', line 160

def send_notification
  return unless notify? || notify_staff?

  InternalMailer.praise_email(self).deliver_later
end

#source_nameObject



240
241
242
243
244
# File 'app/models/praise.rb', line 240

def source_name
  source.presence ||
    (originating_party || originating_employee_record.try(:party)).try(:full_name) ||
    'WarmlyYours'
end

#title(max_length: 100) ⇒ Object



246
247
248
# File 'app/models/praise.rb', line 246

def title(max_length: 100)
  (headline || praise).truncate(max_length)
end

#to_sObject



203
204
205
# File 'app/models/praise.rb', line 203

def to_s
  headline.try(:titleize) || "#{praise_type.humanize} for #{recipient_name}"
end

#validate_awards_uniqueness(awards) ⇒ Object



207
208
209
210
211
212
213
214
215
# File 'app/models/praise.rb', line 207

def validate_awards_uniqueness(awards)
  # Employee can only get one award of this type in the provided period
  errors.add(:praise_type, 'already exists for this employee for this period') if awards.map { |a| a.employee_records }.include?(employee_records)

  # Employee cannot conflict with another ranking for the same award's rank
  return unless awards.where(rank: rank).exists?

  errors.add(:rank, 'already exists for this award for this period')
end

#validate_customer_praiseObject



223
224
225
226
227
228
229
230
# File 'app/models/praise.rb', line 223

def validate_customer_praise
  # Remove unecessary values
  self.rank = nil
  self.originating_employee_record_id = nil
  return unless originating_party and !%w[Contact Customer].include? originating_party.class.name

  errors.add(:originating_party_id, 'must be a contact or customer when specified')
end

#validate_employee_praiseObject



217
218
219
220
221
# File 'app/models/praise.rb', line 217

def validate_employee_praise
  return unless originating_employee_record_id && employee_record_id && originating_employee_record_id == employee_record_id

  errors.add(:employee_record_id, 'cannot be the same as originating employee giving the praise')
end

#validate_monthly_sales_awardObject



183
184
185
186
187
188
189
190
# File 'app/models/praise.rb', line 183

def validate_monthly_sales_award
  return unless praise_date

  self.headline ||= "Monthly Sales Award #{praise_date.strftime('%B %Y')}"
  # Only a single top dog award per month for a given employee
  monthly_awards = Praise.monthly_sales_award.where(praise_date: praise_date.all_month).where.not(id: id.to_i)
  validate_awards_uniqueness monthly_awards
end

#validate_praise_or_image_presentObject



174
175
176
177
178
179
180
181
# File 'app/models/praise.rb', line 174

def validate_praise_or_image_present
  return unless is_a_praise?
  return if image.present? or praise.present?

  errors.add(:base, 'An image or praise must be specified')
  errors.add(:image, '')
  errors.add(:praise, '')
end

#validate_yearly_sales_awardObject



192
193
194
195
196
197
198
199
200
201
# File 'app/models/praise.rb', line 192

def validate_yearly_sales_award
  self.headline = if rank == 1
                    "Alpha Dog of the year #{praise_date.strftime('%Y')}"
                  else
                    "Yearly Sales Award ##{rank} #{praise_date.strftime('%Y')}"
                  end
  # Only a single top dog award per year for a given employee
  yearly_awards = Praise.yearly_sales_award.where(praise_date: praise_date.all_year).where.not(id: id.to_i)
  validate_awards_uniqueness yearly_awards
end