Class: TimeCop::Accountability

Inherits:
Object
  • Object
show all
Defined in:
lib/time_cop/accountability.rb

Constant Summary collapse

DAYS_PER_WEEK =
5.0
QUARTERLY_PERIODS =
{
  q1: [{month: 1, day: 1}, {month: 3, day: 31}],
  q2: [{month: 4, day: 1}, {month: 6, day: 30}],
  q3: [{month: 7, day: 1}, {month: 9, day: 30}],
  q4: [{month: 10, day: 1}, {month: 12, day: 31}]
}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(harvest_client:, date: Date.today, today: Date.today, report_builder: nil, email: nil, hours_per_week: 32) ⇒ Accountability

Returns a new instance of Accountability.



18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'lib/time_cop/accountability.rb', line 18

def initialize(harvest_client:, date: Date.today, today: Date.today, report_builder: nil, email: nil, hours_per_week: 32)
  @client = harvest_client
  @date = date
  @today = today
  @hours_per_week = hours_per_week
  @report_builder = report_builder ||
    ReportBuilder.new(
      client: client,
      user: (email ? fetch_user(email) : default_user),
      start_date: start_of_quarter_date,
      end_date: end_of_quarter_date
    )
end

Instance Attribute Details

#clientObject (readonly)

Returns the value of attribute client.



7
8
9
# File 'lib/time_cop/accountability.rb', line 7

def client
  @client
end

#dateObject (readonly)

Returns the value of attribute date.



7
8
9
# File 'lib/time_cop/accountability.rb', line 7

def date
  @date
end

#hours_per_weekObject (readonly)

Returns the value of attribute hours_per_week.



7
8
9
# File 'lib/time_cop/accountability.rb', line 7

def hours_per_week
  @hours_per_week
end

#report_builderObject (readonly)

Returns the value of attribute report_builder.



7
8
9
# File 'lib/time_cop/accountability.rb', line 7

def report_builder
  @report_builder
end

#todayObject (readonly)

Returns the value of attribute today.



7
8
9
# File 'lib/time_cop/accountability.rb', line 7

def today
  @today
end

Class Method Details

.paint_number(number) ⇒ Object



153
154
155
# File 'lib/time_cop/accountability.rb', line 153

def self.paint_number(number)
  Paint[number, (number >= 0 ? :green : :red)]
end

Instance Method Details

#accountObject



36
37
38
# File 'lib/time_cop/accountability.rb', line 36

def 
  client.
end

#active_quarter?Boolean

Returns:

  • (Boolean)


64
65
66
67
# File 'lib/time_cop/accountability.rb', line 64

def active_quarter?
  quarter_range = (date_from_period(get_quarter[0])...date_from_period(get_quarter[1]))
  quarter_range.include?(Date.today)
end

#average_quarter_hours_per_dayObject



125
126
127
128
129
130
131
# File 'lib/time_cop/accountability.rb', line 125

def average_quarter_hours_per_day
  if weekdays_so_far(false) > 0
    total_quarter_time_tracked / weekdays_so_far(false)
  else
    0
  end
end

#current_hours_deltaObject



137
138
139
# File 'lib/time_cop/accountability.rb', line 137

def current_hours_delta
  total_quarter_time_tracked - expected_quarter_hours_to_today
end

#date_from_period(period) ⇒ Object



48
49
50
# File 'lib/time_cop/accountability.rb', line 48

def date_from_period(period)
    Date.new(date.year, period[:month], period[:day])
end

#default_userObject



44
45
46
# File 'lib/time_cop/accountability.rb', line 44

def default_user
  .who_am_i
end

#end_of_quarter_dateObject



77
78
79
# File 'lib/time_cop/accountability.rb', line 77

def end_of_quarter_date
  date_from_period(get_quarter[1])
end

#expected_quarter_hoursObject



117
118
119
# File 'lib/time_cop/accountability.rb', line 117

def expected_quarter_hours
  total_week_days.to_f * hours_per_day
end

#expected_quarter_hours_to_todayObject



121
122
123
# File 'lib/time_cop/accountability.rb', line 121

def expected_quarter_hours_to_today
  weekdays_between(start_of_quarter_date, today < end_of_quarter_date ? Date.today : end_of_quarter_date) * hours_per_day
end

#fetch_user(email) ⇒ Object



40
41
42
# File 'lib/time_cop/accountability.rb', line 40

def fetch_user(email)
  client.users.find(email)
end

#get_quarterObject



69
70
71
# File 'lib/time_cop/accountability.rb', line 69

def get_quarter
  select_quarter.first[1]
end

#hours_per_dayObject



32
33
34
# File 'lib/time_cop/accountability.rb', line 32

def hours_per_day
  @hours_per_week / DAYS_PER_WEEK
end


179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# File 'lib/time_cop/accountability.rb', line 179

def print_report
  puts "Quarter Period: #{start_of_quarter_date} - #{end_of_quarter_date}"
  puts "Hours Per Week: #{@hours_per_week}"
  puts ""
  puts "Quarterly Hour Target: #{expected_quarter_hours.round(2)}"
  puts "Quarterly Hours Charged: #{total_quarter_time_tracked.round(2)}"
  if active_quarter?
    puts ""
    puts "Business Days Left In The Quarter (Excluding Today): #{weekdays_left(false)}"
    puts ""
    puts "Additional Hours Needed By End Of Quarter: #{quarterly_hours_delta.round(2)}"
    puts "Average Hours Per Business Day Worked: #{average_quarter_hours_per_day.round(2)}"
    puts "Hours Per Business Day Average Needed: #{quarterly_hours_per_business_day_needed.round(2)}"
  end
  puts""
  puts "Quarter Surplus(+)/Deficit(-): #{Accountability.paint_number(current_hours_delta.round(2))}"
  puts "Projected Surplus(+)/Deficit(-): #{Accountability.paint_number(projected_quarter_hours.round(2))}" if active_quarter?
end

#projected_quarter_hoursObject



133
134
135
# File 'lib/time_cop/accountability.rb', line 133

def projected_quarter_hours
  ((total_quarter_time_tracked + (weekdays_left(false) * average_quarter_hours_per_day)) - expected_quarter_hours)
end

#quarterly_hours_deltaObject



141
142
143
# File 'lib/time_cop/accountability.rb', line 141

def quarterly_hours_delta
  expected_quarter_hours - total_quarter_time_tracked
end

#quarterly_hours_per_business_day_neededObject



145
146
147
148
149
150
151
# File 'lib/time_cop/accountability.rb', line 145

def quarterly_hours_per_business_day_needed
  if weekdays_between(today, end_of_quarter_date) == 0
    quarterly_hours_delta
  else
    quarterly_hours_delta / weekdays_between(today, end_of_quarter_date).to_f
  end
end

#quarterly_tracked_time_by_userObject



81
82
83
# File 'lib/time_cop/accountability.rb', line 81

def quarterly_tracked_time_by_user
  @quarterly_tracked_time_by_user ||= report_builder.generate
end

#select_quarterObject



52
53
54
55
56
57
58
59
60
61
62
# File 'lib/time_cop/accountability.rb', line 52

def select_quarter
  QUARTERLY_PERIODS.select do |quarter, range|
    start_of_range = range[0]
    end_of_range = range[1]

    start_date_of_range = date_from_period(start_of_range)
    end_date_of_range = date_from_period(end_of_range)

    (date >= start_date_of_range) && (date <= end_date_of_range)
  end
end

#start_of_quarter_dateObject



73
74
75
# File 'lib/time_cop/accountability.rb', line 73

def start_of_quarter_date
  date_from_period(get_quarter[0])
end

#summary_hashObject



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/time_cop/accountability.rb', line 157

def summary_hash
  {
    quarter: {
      start: start_of_quarter_date,
      end: end_of_quarter_date,
      weekdays_in_quarter: weekdays_between(@report_builder.start_date, @report_builder.end_date),
      weekdays_so_far: weekdays_so_far,
      weekdays_left: weekdays_left
    },
    hours_per_week: @hours_per_week,
    hours: {
      charged: total_quarter_time_tracked,
      needed: expected_quarter_hours,
      left: quarterly_hours_delta,
      average_charged: average_quarter_hours_per_day,
      average_needed: quarterly_hours_per_business_day_needed,
      current_hours: current_hours_delta,
      total_projected: projected_quarter_hours
    }
  }
end

#total_quarter_daysObject



89
90
91
# File 'lib/time_cop/accountability.rb', line 89

def total_quarter_days
  (end_of_quarter_date - start_of_quarter_date).to_i
end

#total_quarter_time_trackedObject



85
86
87
# File 'lib/time_cop/accountability.rb', line 85

def total_quarter_time_tracked
  quarterly_tracked_time_by_user.map { |t| t.hours }.reduce(0, :+)
end

#total_week_daysObject



113
114
115
# File 'lib/time_cop/accountability.rb', line 113

def total_week_days
  weekdays_between(start_of_quarter_date, end_of_quarter_date)
end

#weekdays_between(start_date, end_date) ⇒ Object



109
110
111
# File 'lib/time_cop/accountability.rb', line 109

def weekdays_between(start_date, end_date)
  (start_date..end_date).select{|d| (1..5).include?(d.wday)}.size
end

#weekdays_left(include_today = false) ⇒ Object



93
94
95
96
97
98
99
# File 'lib/time_cop/accountability.rb', line 93

def weekdays_left(include_today = false)
  if include_today
    weekdays_between(Date.today, end_of_quarter_date)
  else
    weekdays_between(Date.today + 1, end_of_quarter_date)
  end
end

#weekdays_so_far(include_today = true) ⇒ Object



101
102
103
104
105
106
107
# File 'lib/time_cop/accountability.rb', line 101

def weekdays_so_far(include_today = true)
  if include_today
    weekdays_between(start_of_quarter_date, Date.today)
  else
    weekdays_between(start_of_quarter_date, Date.today - 1)
  end
end