Class: DailyFocus::RunPolicy

Inherits:
Object
  • Object
show all
Defined in:
app/services/daily_focus/run_policy.rb

Overview

Decides which reps (sales by default, technical support via +audience:+) receive an
automated Daily Focus job for a calendar day, using schedule capacity
(Employee#working_on_day? / capacity_ratio) and backup pairing
(EmployeeRecord#backup_rep) to roll covered reps into their working backup's briefing.

Reps who are not working that day do not get their own job; if they have a backup who
is working and is also an active sales rep, their scope is merged into the backup's run.

Defined Under Namespace

Classes: Target

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(date: Date.current, employee_scope: nil, working_predicate: nil, audience: :sales) ⇒ RunPolicy

Returns a new instance of RunPolicy.

Parameters:

  • date (Date) (defaults to: Date.current)
  • employee_scope (ActiveRecord::Relation, nil) (defaults to: nil)

    Optional subset of employees (e.g. tests).

  • working_predicate (Proc, nil) (defaults to: nil)

    Optional +call(employee)+ override for schedule (true = working that day).

  • audience (String, Symbol) (defaults to: :sales)

    'sales' (default) or 'support' — which rep population to target.



88
89
90
91
92
93
# File 'app/services/daily_focus/run_policy.rb', line 88

def initialize(date: Date.current, employee_scope: nil, working_predicate: nil, audience: :sales)
  @date = date
  @employee_scope = employee_scope
  @working_predicate = working_predicate
  @audience = audience
end

Class Method Details

.covering_conversation_for(date:, employee_id:, audience: :sales) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
# File 'app/services/daily_focus/run_policy.rb', line 15

def self.covering_conversation_for(date:, employee_id:, audience: :sales)
  eid = employee_id.to_i
  return nil if eid <= 0

  AssistantConversation
    .for_daily_focus_date(date)
    .for_daily_focus_audience(audience)
    .where("COALESCE((metadata->'daily_focus_covered_employee_ids')::jsonb, '[]'::jsonb) @> ?", [eid].to_json)
    .order(updated_at: :desc)
    .first
end

.covering_rows_for_review(date:, rep_ids:, audience: :sales) ⇒ Hash

One query for all "covered" reps on the review page instead of N calls to +covering_conversation_for+.

Returns:

  • (Hash)

    rep_id (Integer) => { conversation:, covering_rep: }



29
30
31
32
33
34
35
36
37
38
39
40
# File 'app/services/daily_focus/run_policy.rb', line 29

def self.covering_rows_for_review(date:, rep_ids:, audience: :sales)
  rep_id_set = rep_ids.to_set(&:to_i)
  return {} if rep_id_set.empty?

  convs = conversations_with_covered_reps(date, audience)
  rep_to_conv = index_covering_conversation_by_rep(convs, rep_id_set)
  primary_by_conv_id = index_covering_primary_by_conversation(rep_to_conv.values.uniq)

  rep_to_conv.transform_values do |conv|
    { conversation: conv, covering_rep: primary_by_conv_id[conv.id] }
  end
end

Instance Method Details

#automation_targetsArray<Target>

Returns One target per working sales rep (may include covered_employee_ids).

Returns:

  • (Array<Target>)

    One target per working sales rep (may include covered_employee_ids).



96
97
98
# File 'app/services/daily_focus/run_policy.rb', line 96

def automation_targets
  @automation_targets ||= compute_automation_targets
end

#covered_rep_idsObject

Rep ids whose briefing is folded into another rep's run (no standalone job).



101
102
103
# File 'app/services/daily_focus/run_policy.rb', line 101

def covered_rep_ids
  automation_targets.flat_map(&:covered_employee_ids).uniq
end