Class: SalesRepQueueEntry
Overview
== Schema Information
Table name: sales_rep_queue_entries
Database name: primary
id :integer not null, primary key
apply_paired_sales_rep :boolean
local_sales_rep_ids :integer default([]), is an Array
local_sales_rep_stack :integer default([]), is an Array
local_sales_rep_weights :integer default([]), is an Array
name :string(255)
position :integer
primary_sales_rep_ids :integer default([]), is an Array
primary_sales_rep_stack :integer default([]), is an Array
primary_sales_rep_weights :integer default([]), is an Array
secondary_sales_rep_ids :integer default([]), is an Array
secondary_sales_rep_stack :integer default([]), is an Array
secondary_sales_rep_weights :integer default([]), is an Array
created_at :datetime
updated_at :datetime
creator_id :integer
customer_filter_id :integer
sales_rep_queue_id :integer
updater_id :integer
Indexes
idx_sales_rep_queue_id (sales_rep_queue_id)
sales_rep_queue_entries_customer_filter_id_idx (customer_filter_id)
Foreign Keys
sales_rep_queue_entries_customer_filter_id_fk (customer_filter_id => customer_filters.id)
Constant Summary
Models::Auditable::ALWAYS_IGNORED
Instance Attribute Summary collapse
#creator, #updater
Class Method Summary
collapse
Instance Method Summary
collapse
#all_skipped_columns, #audit_reference_data, #should_not_save_version, #stamp_record
ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation
#publish_event
Instance Attribute Details
#customer_filter_id ⇒ Object
48
|
# File 'app/models/sales_rep_queue_entry.rb', line 48
validates :customer_filter_id, uniqueness: { scope: :sales_rep_queue_id }
|
#name ⇒ Object
46
|
# File 'app/models/sales_rep_queue_entry.rb', line 46
validates :name, :sales_rep_queue, presence: true
|
Class Method Details
.name_map(rel, role_prefix, include_token = true) ⇒ Object
81
82
83
84
85
86
87
|
# File 'app/models/sales_rep_queue_entry.rb', line 81
def self.name_map(rel, role_prefix, include_token=true)
rel.map do |srw|
res = "#{srw.employee.full_name}"
res << " [#{role_prefix}:#{srw.weight}:#{srw.effective_remaining}(#{srw.remaining})]" if include_token
res
end
end
|
A relation of SalesRepQueueEntries that are sorted. Active Record Scope
53
|
# File 'app/models/sales_rep_queue_entry.rb', line 53
scope :sorted, -> { order("sales_rep_queue_entries.position") }
|
Instance Method Details
#all_rep_names(include_token = true) ⇒ Object
101
102
103
104
105
|
# File 'app/models/sales_rep_queue_entry.rb', line 101
def all_rep_names(include_token=true)
(primary_sales_reps_names(include_token) +
secondary_sales_reps_names(include_token) +
local_sales_reps_names(include_token)).uniq
end
|
#applies_to_customer?(customer) ⇒ Boolean
69
70
71
|
# File 'app/models/sales_rep_queue_entry.rb', line 69
def applies_to_customer?(customer)
sales_rep_weights.present? and (customer_filter ? customer_filter.applies_to_customer?(customer) : true)
end
|
#assign_combined_values(rep_type, val) ⇒ Object
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
|
# File 'app/models/sales_rep_queue_entry.rb', line 119
def assign_combined_values(rep_type, val)
rep_type = rep_type.to_s
return unless val.present?
valids = []
val.each do |rep_id, weight|
rep_id = rep_id.to_i
weight = weight.to_i
if weight > 0
obj = sales_rep_weights.detect{ |srw| srw.employee_id == rep_id && srw.role == rep_type }
if obj.nil?
obj = sales_rep_weights.build(employee_id: rep_id, role: rep_type, weight: weight)
else
obj.weight = weight
end
if obj.valid?
valids << obj
else
raise "Sales rep weight for #{obj.role} id #{rep_id} with value #{weight} is invalid, #{obj.errors_to_s}"
end
end
end
sales_rep_weights.select{|srw| srw.role == rep_type}.reject{|srw| valids.map(&:id).include?(srw.id) }.each(&:destroy)
end
|
#available_customer_filters ⇒ Object
55
56
57
58
59
60
61
62
63
|
# File 'app/models/sales_rep_queue_entry.rb', line 55
def available_customer_filters
CustomerFilter.options_for_select do |rel|
filter_in_use_ids = SalesRepQueueEntry.where(sales_rep_queue_id: sales_rep_queue_id).pluck(:customer_filter_id) - [customer_filter_id]
filter_in_use_ids = filter_in_use_ids.compact.uniq
newrel = rel.where(store_id: sales_rep_queue.store_id)
newrel = newrel.where("customer_filters.id NOT IN (?)", filter_in_use_ids) if filter_in_use_ids.present?
newrel
end
end
|
#check_sales_rep_queue_rules ⇒ Object
144
145
146
147
148
149
150
151
152
153
154
155
156
|
# File 'app/models/sales_rep_queue_entry.rb', line 144
def check_sales_rep_queue_rules
unless primary_sales_rep_in_queue?
if secondary_sales_rep_in_queue? or local_sales_rep_in_queue?
errors.add(:base, " must have at least one non-zero entry (or Local Sales Rep Weights can have one non-zero entry if 'Apply Paired Sales Rep' is checked)")
elsif secondary_sales_rep_in_queue?
errors.add(:base, " must have at least one non-zero entry if Secondary Sales Rep Weights has one non-zero entry")
end
if local_sales_rep_in_queue? and !apply_paired_sales_rep?
errors.add(:base, " must have at least one non-zero entry if Local Sales Rep Weights has one non-zero entry and 'Apply Paired Sales Rep' is not checked")
end
end
end
|
42
|
# File 'app/models/sales_rep_queue_entry.rb', line 42
belongs_to :customer_filter, inverse_of: :sales_rep_queue_entries, optional: true
|
#default? ⇒ Boolean
65
66
67
|
# File 'app/models/sales_rep_queue_entry.rb', line 65
def default?
customer_filter.nil?
end
|
#description ⇒ Object
77
78
79
|
# File 'app/models/sales_rep_queue_entry.rb', line 77
def description
"#{sales_rep_queue} - #{name} : #{all_rep_names(true).join(', ')}"
end
|
#find_sales_rep_weight_for(role, sales_rep_id) ⇒ Object
199
200
201
|
# File 'app/models/sales_rep_queue_entry.rb', line 199
def find_sales_rep_weight_for(role, sales_rep_id)
sales_rep_weights.where(role: role, employee_id: sales_rep_id).pick(:weight) || 0
end
|
#get_assignable_weights(sales_rep_type) ⇒ Object
178
179
180
181
182
183
184
185
|
# File 'app/models/sales_rep_queue_entry.rb', line 178
def get_assignable_weights(sales_rep_type)
weights = sales_rep_weights.reload.assignable.where(role: sales_rep_type).select{|w| w.effective_remaining.positive? }
unless weights.present?
reset_weights(sales_rep_type)
weights = sales_rep_weights.reload.assignable.where(role: sales_rep_type).select{|w| w.effective_remaining.positive? }
end
weights.to_a
end
|
#get_sales_rep(sales_rep_type = :primary_sales_rep) ⇒ Object
187
188
189
190
191
192
193
194
195
196
197
|
# File 'app/models/sales_rep_queue_entry.rb', line 187
def get_sales_rep(sales_rep_type = :primary_sales_rep)
weights = get_assignable_weights(sales_rep_type)
if weights.present?
weights.shuffle!
weight = weights.shift
weight.remaining = [weight.remaining - 1, 0].max
weight.save
rep = weight.employee
end
rep
end
|
#local_sales_rep_in_queue? ⇒ Boolean
166
167
168
|
# File 'app/models/sales_rep_queue_entry.rb', line 166
def local_sales_rep_in_queue?
sales_rep_weights.where(role: :local_sales_rep).exists?
end
|
#local_sales_rep_weights_combined=(val) ⇒ Object
115
116
117
|
# File 'app/models/sales_rep_queue_entry.rb', line 115
def local_sales_rep_weights_combined=(val)
assign_combined_values :local_sales_rep, val
end
|
#local_sales_reps_names(include_token = true) ⇒ Object
97
98
99
|
# File 'app/models/sales_rep_queue_entry.rb', line 97
def local_sales_reps_names(include_token=true)
self.class.name_map sales_rep_weights.local_sales_reps.with_employee_sorted, "L", include_token
end
|
#prevent_paired_rep_duplicates ⇒ Object
To prevent duplicate assignment of a rep in multiple role we must validate each rep and potential backup rep in each role
If any are possibly listed twice then we error out
205
206
207
208
209
210
211
212
213
|
# File 'app/models/sales_rep_queue_entry.rb', line 205
def prevent_paired_rep_duplicates
rep_ids = sales_rep_weights.map &:employee_id
if apply_paired_sales_rep
rep_ids += sales_rep_weights.map{|srw| srw.employee.try(:employee_record).try(:backup_rep_id) }.compact
end
duplicate_employee_ids = rep_ids.group_by{|e| e}.select { |k, v| v.size > 1 }.map(&:first)
duplicate_employee_names = Employee.where(id: duplicate_employee_ids).pluck(:full_name)
errors.add(:base, "#{duplicate_employee_names.to_sentence} can potentially be duplicated causing an assignment error, make sure reps only appear in one role.") if duplicate_employee_names.present?
end
|
#primary_sales_rep_in_queue? ⇒ Boolean
158
159
160
|
# File 'app/models/sales_rep_queue_entry.rb', line 158
def primary_sales_rep_in_queue?
sales_rep_weights.where(role: :primary_sales_rep).exists?
end
|
#primary_sales_rep_weights_combined=(val) ⇒ Object
107
108
109
|
# File 'app/models/sales_rep_queue_entry.rb', line 107
def primary_sales_rep_weights_combined=(val)
assign_combined_values :primary_sales_rep, val
end
|
#primary_sales_reps_names(include_token = true) ⇒ Object
89
90
91
|
# File 'app/models/sales_rep_queue_entry.rb', line 89
def primary_sales_reps_names(include_token=true)
self.class.name_map sales_rep_weights.primary_sales_reps.with_employee_sorted, "P", include_token
end
|
#reset_weights(roles = nil) ⇒ Object
170
171
172
173
174
175
176
|
# File 'app/models/sales_rep_queue_entry.rb', line 170
def reset_weights(roles=nil)
roles = [roles].flatten.compact
roles = SalesRepQueue::SALES_REP_TYPES unless roles.present?
logger.debug "Retrieving a fresh stack of rep for #{roles.join} on sales queue #{id}"
sales_rep_weights.where(role: roles).update_all("remaining = weight")
sales_rep_weights.reload end
|
Validations:
41
|
# File 'app/models/sales_rep_queue_entry.rb', line 41
belongs_to :sales_rep_queue, inverse_of: :sales_rep_queue_entries, optional: true
|
#sales_rep_weights ⇒ ActiveRecord::Relation<SalesRepWeight>
44
|
# File 'app/models/sales_rep_queue_entry.rb', line 44
has_many :sales_rep_weights, inverse_of: :sales_rep_queue_entry, autosave: true
|
#secondary_sales_rep_in_queue? ⇒ Boolean
162
163
164
|
# File 'app/models/sales_rep_queue_entry.rb', line 162
def secondary_sales_rep_in_queue?
sales_rep_weights.where(role: :secondary_sales_rep).exists?
end
|
#secondary_sales_rep_weights_combined=(val) ⇒ Object
111
112
113
|
# File 'app/models/sales_rep_queue_entry.rb', line 111
def secondary_sales_rep_weights_combined=(val)
assign_combined_values :secondary_sales_rep, val
end
|
#secondary_sales_reps_names(include_token = true) ⇒ Object
93
94
95
|
# File 'app/models/sales_rep_queue_entry.rb', line 93
def secondary_sales_reps_names(include_token=true)
self.class.name_map sales_rep_weights.secondary_sales_reps.with_employee_sorted, "S", include_token
end
|
#to_s ⇒ Object
73
74
75
|
# File 'app/models/sales_rep_queue_entry.rb', line 73
def to_s
name
end
|