Module: DailyFocus::Prompt
- Extended by:
- TimeOffPlannedWorkDayHelper
- Defined in:
- app/services/daily_focus/prompt.rb
Overview
Short user-facing prompts for tool-based Daily Focus (no pre-injected CRM dumps).
Constant Summary collapse
- EXCLUDE_ETAILERS_SQL =
E-tailer / marketplace accounts (Amazon, Costco, Home Depot, RONA, TJX, and
any other "E-commerce - *" report grouping) are excluded from Daily Focus: they
transact through established EDI, not rep nurturing, so they only add noise to a
briefing meant for professional and homeowner accounts that need human contact.
Both view_activities and view_customers expose the customer's report_grouping; the
COALESCE keeps rows whose grouping is NULL (a bare NULL NOT LIKE … would drop them).
The named list catches the e-tailer groupings that predate the "E-commerce - *"
convention (RONA Canada, Home Depot, …) — it comes from
Customer::ReportGrouping::ETAILER_GROUPINGS so the two can't disagree. "COALESCE(report_grouping, '') NOT LIKE 'E-commerce%' " \ "AND COALESCE(report_grouping, '') NOT IN (#{Customer::ReportGrouping.etailer_groupings_sql_list})"
Class Method Summary collapse
-
.coaching_note_section(primary_employee) ⇒ Object
Standing manager coaching instruction for this rep, set on the Daily Focus review page and reused every day until cleared.
- .focus_date_for_conversation(conversation) ⇒ Object
- .instructions_prefill(primary_employee:, covered_employees: [], date: Date.current) ⇒ Object
-
.user_message(primary_employee:, covered_employees: [], date: Date.current, audience: nil) ⇒ Object
Audience defaults from the employee's roles (DailyFocus.audience_for), so callers never thread it through — pass it only to force a variant (tests).
Methods included from TimeOffPlannedWorkDayHelper
time_off_planned_work_day_planned_hours, time_off_planned_work_day_summary, time_off_planned_work_day_usual_summary
Class Method Details
.coaching_note_section(primary_employee) ⇒ Object
Standing manager coaching instruction for this rep, set on the Daily Focus
review page and reused every day until cleared. Injected right after the
briefing ask (see core_body) so Sunny treats it as a first-class priority
ahead of the mechanical SQL sections. nil when the manager hasn't set one.
Public because both audiences use it — SupportSections calls it too.
61 62 63 64 65 66 67 68 69 70 71 |
# File 'app/services/daily_focus/prompt.rb', line 61 def self.coaching_note_section(primary_employee) body = primary_employee.daily_focus_coaching_note&.body return nil if body.blank? <<~TEXT.squish MANAGER COACHING FOCUS — your manager set specific priorities for #{primary_employee.full_name} today. Treat these as high-priority instructions: surface a prominent "Coaching Focus" section and let them shape which accounts and actions you highlight, on top of the standard briefing. Instructions: #{body} TEXT end |
.focus_date_for_conversation(conversation) ⇒ Object
20 21 22 23 24 25 26 27 |
# File 'app/services/daily_focus/prompt.rb', line 20 def self.focus_date_for_conversation(conversation) raw = conversation&.&.dig('daily_focus_date') return Date.current if raw.blank? Date.iso8601(raw.to_s) rescue ArgumentError Date.current end |
.instructions_prefill(primary_employee:, covered_employees: [], date: Date.current) ⇒ Object
29 30 31 |
# File 'app/services/daily_focus/prompt.rb', line 29 def self.instructions_prefill(primary_employee:, covered_employees: [], date: Date.current) (primary_employee: primary_employee, covered_employees: covered_employees, date: date) end |
.user_message(primary_employee:, covered_employees: [], date: Date.current, audience: nil) ⇒ Object
Audience defaults from the employee's roles (DailyFocus.audience_for), so callers
never thread it through — pass it only to force a variant (tests).
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'app/services/daily_focus/prompt.rb', line 35 def self.(primary_employee:, covered_employees: [], date: Date.current, audience: nil) audience ||= DailyFocus.audience_for(primary_employee) covered = Array(covered_employees).compact.uniq preload_planned_availability!([primary_employee, *covered], date) planned = planned_work_availability_section( primary_employee: primary_employee, covered_employees: covered, date: date ) tz = TimezoneHints.prompt_section(primary_employee: primary_employee, covered_employees: covered) body = if audience.to_s == 'support' SupportSections.body(primary_employee, covered, date) else core_body(primary_employee, covered) end parts = [body] parts << planned if planned.present? parts << tz parts.join(' ') end |