Class: SalesGoal

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

Overview

== Schema Information

Table name: sales_goals
Database name: primary

id :integer not null, primary key
bonus_t1_flat :decimal(6, 2)
bonus_t1_multiplier :decimal(8, 4)
bonus_t2_flat :decimal(6, 2)
bonus_t2_multiplier :decimal(8, 4)
period_begins :date not null
period_ends :date not null
report_grouping :string(255)
sales_goal :decimal(10, 2) default(0.0), not null
sales_goal_t2 :decimal(8, 2)
created_at :datetime
updated_at :datetime
company_id :integer
creator_id :integer
employee_id :integer
updater_id :integer

Indexes

idx_unique_sales_goals (employee_id,report_grouping,period_begins,period_ends)

Constant Summary

Constants included from Models::Auditable

Models::Auditable::ALWAYS_IGNORED

Instance Attribute Summary 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, ransortable_attributes, #to_relation

Methods included from Models::EventPublishable

#publish_event

Instance Attribute Details

#force_syncObject

Returns the value of attribute force_sync.



31
32
33
# File 'app/models/sales_goal.rb', line 31

def force_sync
  @force_sync
end

Class Method Details

.channels_for_selectObject



302
303
304
# File 'app/models/sales_goal.rb', line 302

def self.channels_for_select
  CustomerConstants::REPORT_GROUPINGS
end

.in_periodActiveRecord::Relation<SalesGoal>

A relation of SalesGoals that are in period. Active Record Scope

Returns:

See Also:



60
61
62
63
# File 'app/models/sales_goal.rb', line 60

scope :in_period, -> (date) {
  date = Date.parse(date) unless date.is_a?(Date)
  where(period_begins: ..date , period_ends: date..)
}

.in_same_quarterActiveRecord::Relation<SalesGoal>

A relation of SalesGoals that are in same quarter. Active Record Scope

Returns:

See Also:



56
57
58
59
# File 'app/models/sales_goal.rb', line 56

scope :in_same_quarter, -> (date) {
  date = Date.parse(date) unless date.is_a?(Date)
  where("period_begins >= :boq AND period_begins <= :eoq", boq: date.beginning_of_quarter, eoq: date.end_of_quarter)
}

.monthly_goalsActiveRecord::Relation<SalesGoal>

A relation of SalesGoals that are monthly goals. Active Record Scope

Returns:

See Also:



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

scope :monthly_goals, -> { where('(period_ends - period_begins) BETWEEN 27 and 32') }

.periods(date = nil) ⇒ Object



96
97
98
# File 'app/models/sales_goal.rb', line 96

def self.periods(date = nil)
  [] + periods_for_quarter_for_select(date) + periods_for_year_for_select(date)
end

.periods_for_quarter_for_select(date = nil) ⇒ Object



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

def self.periods_for_quarter_for_select(date = nil)
  date ||= Date.current
  periods = []
  date_start = date.beginning_of_year
  (0..11).to_a.each do |m|
    dt = date_start + m.month
    dt_label = "#{dt.strftime('%B')} #{dt.year}"
    dt_val = "#{dt}|#{dt.end_of_month}"
    periods << [dt_label, dt_val]
  end
  (1..4).to_a.each do |q|
    dt = Date.new(date_start.year, q * 3, 1).beginning_of_quarter
    periods << ["Quarter #{q}, #{dt.year}", "#{dt}|#{dt.end_of_quarter}"]
  end

  periods
end

.periods_for_year_for_select(date = nil) ⇒ Object



89
90
91
92
93
94
# File 'app/models/sales_goal.rb', line 89

def self.periods_for_year_for_select(date = nil)
  date ||= Date.current
  dts = date.beginning_of_year
  dte = date.end_of_year
  periods = [["Year #{date.year}", "#{dts}|#{dte}"]]
end

.quarterly_goalsActiveRecord::Relation<SalesGoal>

A relation of SalesGoals that are quarterly goals. Active Record Scope

Returns:

See Also:



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

scope :quarterly_goals, -> { where('(period_ends - period_begins) BETWEEN 83 and 94') }

.ransackable_scopes(_auth_user = nil) ⇒ Object



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

def self.ransackable_scopes(_auth_user = nil)
  %i[in_same_quarter in_period]
end

.sortedActiveRecord::Relation<SalesGoal>

A relation of SalesGoals that are sorted. Active Record Scope

Returns:

See Also:



65
# File 'app/models/sales_goal.rb', line 65

scope :sorted, -> { order('parties.full_name, sales_goals.period_ends, sales_goals.period_begins DESC, sales_goals.report_grouping') }

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)


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

def active?
  period_begins <= Date.current and period_ends >= Date.current
end

#all_standard_monthly_goals_in_periodObject



275
276
277
278
279
# File 'app/models/sales_goal.rb', line 275

def all_standard_monthly_goals_in_period
  if employee_id
    SalesGoal.monthly_goals.in_same_quarter(period_begins).where(employee_id: employee_id).where(report_grouping: nil)
  end
end

#bonus_t1Object



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

def bonus_t1
  bonus = nil
  if met_t1? && !met_t2?
    bonus = 0.0
    bonus += booked * bonus_t1_multiplier if bonus_t1_multiplier
    bonus += bonus_t1_flat if bonus_t1_flat
    bonus = nil if bonus <= 0
  end
  bonus
end

#bonus_t2Object



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

def bonus_t2
  bonus = nil
  if met_t2?
    bonus = 0.0
    bonus += booked * bonus_t2_multiplier if bonus_t2_multiplier
    bonus += bonus_t2_flat if bonus_t2_flat
    bonus = nil if bonus <= 0
  end
  bonus
end

#bookedObject



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

def booked
  inv = Invoice.sales_orders.where('invoices.shipped_date BETWEEN ? and ?', period_begins, period_ends)
  inv = inv.where(primary_sales_rep_id: employee_id) if employee_id
  inv = inv.where(report_grouping: report_grouping) if report_grouping.present?
  inv = inv.where(company_id: company_id) if company_id.present?
  inv.sum(:revenue_consolidated) || 0.00
end

#business_days_leftObject



152
153
154
155
156
# File 'app/models/sales_goal.rb', line 152

def business_days_left
  if (Date.current >= period_begins) && (Date.current <= period_ends)
    Date.current.working_days_until(period_ends)
  end
end

#companyCompany

Returns:

See Also:



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

belongs_to :company, optional: true

#daily_target_t1Object



158
159
160
161
162
# File 'app/models/sales_goal.rb', line 158

def daily_target_t1
  if (bdl = business_days_left) && (rt = remaining_t1)
    rt / bdl
  end
end

#daily_target_t2Object



164
165
166
167
168
# File 'app/models/sales_goal.rb', line 164

def daily_target_t2
  if (bdl = business_days_left) && (rt = remaining_t2)
    rt / bdl
  end
end

#editable?Boolean

Returns:

  • (Boolean)


260
261
262
263
# File 'app/models/sales_goal.rb', line 260

def editable?
  # Allowing up to 2 weeks to edit
  new_record? || period_ends > (Date.current + 2.weeks)
end

#employeeEmployee

Returns:

See Also:



33
# File 'app/models/sales_goal.rb', line 33

belongs_to :employee, optional: true

#goal_nameObject



134
135
136
137
138
139
140
141
142
# File 'app/models/sales_goal.rb', line 134

def goal_name
  n = []
  n << employee.full_name if employee
  n << report_grouping if report_grouping
  n << period_name
  n << Company.find(company_id).short_name if company_id.present?
  n << 'goal'
  n.join(' ')
end

#has_prequisite?Boolean

Returns:

  • (Boolean)


256
257
258
# File 'app/models/sales_goal.rb', line 256

def has_prequisite?
  prerequisite_goal.present?
end

#has_tier2_goal?Boolean

Returns:

  • (Boolean)


252
253
254
# File 'app/models/sales_goal.rb', line 252

def has_tier2_goal?
  employee_id.present? && sales_goal_t2.present? && sales_goal_t2 > 0
end

#met_t1?Boolean

Returns:

  • (Boolean)


202
203
204
# File 'app/models/sales_goal.rb', line 202

def met_t1?
  prerequisite_goal_met? and booked >= sales_goal
end

#met_t2?Boolean

Returns:

  • (Boolean)


206
207
208
# File 'app/models/sales_goal.rb', line 206

def met_t2?
  met_t1? and sales_goal_t2 and booked >= sales_goal_t2
end

#month?Boolean

Returns:

  • (Boolean)


116
117
118
# File 'app/models/sales_goal.rb', line 116

def month?
  (period_ends - period_begins) <= 31
end

#periodObject



104
105
106
# File 'app/models/sales_goal.rb', line 104

def period
  "#{period_begins}|#{period_ends}"
end

#period=(val) ⇒ Object



100
101
102
# File 'app/models/sales_goal.rb', line 100

def period=(val)
  self.period_begins, self.period_ends = val.split('|').map { |v| Date.strptime(v, '%Y-%m-%d') }
end

#period_nameObject



120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'app/models/sales_goal.rb', line 120

def period_name
  return unless period_begins && period_ends
  if year?
    "Year #{period_begins.year}"
  elsif quarter?
    quarter = period_begins.quarter_index
    "Quarter #{quarter}, #{period_begins.year}"
  elsif month?
    "#{period_begins.strftime('%B')} #{period_begins.year}"
  else
    "#{period_begins} - #{period_ends}"
  end
end

#prerequisite_goalObject



240
241
242
243
244
245
246
247
248
249
250
# File 'app/models/sales_goal.rb', line 240

def prerequisite_goal
  prg = nil
  if employee_id && report_grouping
    # Find sales goal for group if present
    prg = SalesGoal.where(period_begins: period_begins,
                          period_ends: period_ends,
                          report_grouping: report_grouping,
                          employee_id: nil).first
  end
  prg
end

#prerequisite_goal_met?Boolean

Returns:

  • (Boolean)


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

def prerequisite_goal_met?
  if prerequisite_goal
    prerequisite_goal.met_t1?
  else
    true
  end
end

#progress_t1Object



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

def progress_t1
  if sales_goal && (sales_goal > 0)
    if booked > 0
      [((booked / sales_goal) * 100).to_i, 100].min
    else
      0
    end
  end
end

#progress_t2Object



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

def progress_t2
  if sales_goal_t2 && (sales_goal_t2 > 0)
    if booked > 0
      [((booked / sales_goal_t2) * 100).to_i, 100].min
    else
      0
    end
  end
end

#quarter?Boolean

Returns:

  • (Boolean)


112
113
114
# File 'app/models/sales_goal.rb', line 112

def quarter?
  !year? && (period_ends - period_begins) > 31
end

#remaining_t1Object



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

def remaining_t1
  [sales_goal - booked, 0].max if sales_goal && (sales_goal > 0)
end

#remaining_t2Object



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

def remaining_t2
  [sales_goal_t2 - booked, 0].max if sales_goal_t2 && (sales_goal > 0)
end

#spanObject



265
266
267
268
269
270
271
272
273
# File 'app/models/sales_goal.rb', line 265

def span
  if quarter?
    'Quarter'
  elsif month?
    'Month'
  else
    'Custom'
  end
end

#year?Boolean

Returns:

  • (Boolean)


108
109
110
# File 'app/models/sales_goal.rb', line 108

def year?
  (period_ends - period_begins) >= 364
end